diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index 5d5e8ae94e0..b58b3998345 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -231,6 +231,11 @@ static bool have_xact_temporary_files = false; */ static uint64 temporary_files_size = 0; +/* Temporary file access initialized and not yet shut down? */ +#ifdef USE_ASSERT_CHECKING +static bool temporary_files_allowed = false; +#endif + /* * List of OS handles opened with AllocateFile, AllocateDir and * OpenTransientFile. @@ -327,7 +332,7 @@ static File OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError); static bool reserveAllocatedDesc(void); static int FreeDesc(AllocateDesc *desc); -static void AtProcExit_Files(int code, Datum arg); +static void BeforeShmemExit_Files(int code, Datum arg); static void CleanupTempFiles(bool isCommit, bool isProcExit); static void RemovePgTempRelationFiles(const char *tsdirname); static void RemovePgTempRelationFilesInDbspace(const char *dbspacedirname); @@ -868,6 +873,9 @@ durable_rename_excl(const char *oldfile, const char *newfile, int elevel) * * This is called during either normal or standalone backend start. * It is *not* called in the postmaster. + * + * Note that this does not initialize temporary file access, that is + * separately initialized via InitTemporaryFileAccess(). */ void InitFileAccess(void) @@ -885,9 +893,35 @@ InitFileAccess(void) VfdCache->fd = VFD_CLOSED; SizeVfdCache = 1; +} - /* register proc-exit hook to ensure temp files are dropped at exit */ - on_proc_exit(AtProcExit_Files, 0); +/* + * InitTemporaryFileAccess --- initialize temporary file access during startup + * + * This is called during either normal or standalone backend start. + * It is *not* called in the postmaster. + * + * This is separate from InitFileAccess() because temporary file cleanup can + * cause pgstat reporting. As pgstat is shut down during before_shmem_exit(), + * our reporting has to happen before that. Low level file access should be + * available for longer, hence the separate initialization / shutdown of + * temporary file handling. + */ +void +InitTemporaryFileAccess(void) +{ + Assert(SizeVfdCache != 0); /* InitFileAccess() needs to have run*/ + Assert(!temporary_files_allowed); /* call me only once */ + + /* + * Register before-shmem-exit hook to ensure temp files are dropped while + * we can still report stats. + */ + before_shmem_exit(BeforeShmemExit_Files, 0); + +#ifdef USE_ASSERT_CHECKING + temporary_files_allowed = true; +#endif } /* @@ -1670,6 +1704,8 @@ OpenTemporaryFile(bool interXact) { File file = 0; + Assert(temporary_files_allowed); /* check temp file access is up */ + /* * Make sure the current resource owner has space for this File before we * open it, if we'll be registering it below. @@ -1805,6 +1841,8 @@ PathNameCreateTemporaryFile(const char *path, bool error_on_failure) { File file; + Assert(temporary_files_allowed); /* check temp file access is up */ + ResourceOwnerEnlargeFiles(CurrentResourceOwner); /* @@ -1843,6 +1881,8 @@ PathNameOpenTemporaryFile(const char *path, int mode) { File file; + Assert(temporary_files_allowed); /* check temp file access is up */ + ResourceOwnerEnlargeFiles(CurrentResourceOwner); file = PathNameOpenFile(path, mode | PG_BINARY); @@ -3004,15 +3044,20 @@ AtEOXact_Files(bool isCommit) } /* - * AtProcExit_Files + * BeforeShmemExit_Files * - * on_proc_exit hook to clean up temp files during backend shutdown. + * before_shmem_access hook to clean up temp files during backend shutdown. * Here, we want to clean up *all* temp files including interXact ones. */ static void -AtProcExit_Files(int code, Datum arg) +BeforeShmemExit_Files(int code, Datum arg) { CleanupTempFiles(false, true); + + /* prevent further temp files from being created */ +#ifdef USE_ASSERT_CHECKING + temporary_files_allowed = false; +#endif } /* diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 87dc060b201..5089dd43ae2 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -517,6 +517,12 @@ BaseInit(void) */ DebugFileOpen(); + /* + * Initialize file access. Done early so other subsystems can access + * files. + */ + InitFileAccess(); + /* * Initialize statistics reporting. This needs to happen early to ensure * that pgstat's shutdown callback runs after the shutdown callbacks of @@ -525,11 +531,16 @@ BaseInit(void) */ pgstat_initialize(); - /* Do local initialization of file, storage and buffer managers */ - InitFileAccess(); + /* Do local initialization of storage and buffer managers */ InitSync(); smgrinit(); InitBufferPoolAccess(); + + /* + * Initialize temporary file access after pgstat, so that the temorary + * file shutdown hook can report temporary file statistics. + */ + InitTemporaryFileAccess(); } diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h index 2d843eb9929..34602ae0069 100644 --- a/src/include/storage/fd.h +++ b/src/include/storage/fd.h @@ -158,6 +158,7 @@ extern int MakePGDirectory(const char *directoryName); /* Miscellaneous support routines */ extern void InitFileAccess(void); +extern void InitTemporaryFileAccess(void); extern void set_max_safe_fds(void); extern void closeAllVfds(void); extern void SetTempTablespaces(Oid *tableSpaces, int numSpaces);