diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index a5446d54bb..eb9e0221f8 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -993,7 +993,113 @@ PostmasterMain(int argc, char *argv[]) */ InitializeMaxBackends(); - /* Report server startup in log */ + /* + * Set up shared memory and semaphores. + */ + reset_shared(); + + /* + * Estimate number of openable files. This must happen after setting up + * semaphores, because on some platforms semaphores count as open files. + */ + set_max_safe_fds(); + + /* + * Set reference point for stack-depth checking. + */ + set_stack_base(); + + /* + * Initialize pipe (or process handle on Windows) that allows children to + * wake up from sleep on postmaster death. + */ + InitPostmasterDeathWatchHandle(); + +#ifdef WIN32 + + /* + * Initialize I/O completion port used to deliver list of dead children. + */ + win32ChildQueue = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1); + if (win32ChildQueue == NULL) + ereport(FATAL, + (errmsg("could not create I/O completion port for child queue"))); +#endif + +#ifdef EXEC_BACKEND + /* Write out nondefault GUC settings for child processes to use */ + write_nondefault_variables(PGC_POSTMASTER); + + /* + * Clean out the temp directory used to transmit parameters to child + * processes (see internal_forkexec, below). We must do this before + * launching any child processes, else we have a race condition: we could + * remove a parameter file before the child can read it. It should be + * safe to do so now, because we verified earlier that there are no + * conflicting Postgres processes in this data directory. + */ + RemovePgTempFilesInDir(PG_TEMP_FILES_DIR, true, false); +#endif + + /* + * Forcibly remove the files signaling a standby promotion request. + * Otherwise, the existence of those files triggers a promotion too early, + * whether a user wants that or not. + * + * This removal of files is usually unnecessary because they can exist + * only during a few moments during a standby promotion. However there is + * a race condition: if pg_ctl promote is executed and creates the files + * during a promotion, the files can stay around even after the server is + * brought up to new master. Then, if new standby starts by using the + * backup taken from that master, the files can exist at the server + * startup and should be removed in order to avoid an unexpected + * promotion. + * + * Note that promotion signal files need to be removed before the startup + * process is invoked. Because, after that, they can be used by + * postmaster's SIGUSR1 signal handler. + */ + RemovePromoteSignalFiles(); + + /* Do the same for logrotate signal file */ + RemoveLogrotateSignalFiles(); + + /* Remove any outdated file holding the current log filenames. */ + if (unlink(LOG_METAINFO_DATAFILE) < 0 && errno != ENOENT) + ereport(LOG, + (errcode_for_file_access(), + errmsg("could not remove file \"%s\": %m", + LOG_METAINFO_DATAFILE))); + + /* + * If enabled, start up syslogger collection subprocess + */ + SysLoggerPID = SysLogger_Start(); + + /* + * Reset whereToSendOutput from DestDebug (its starting state) to + * DestNone. This stops ereport from sending log messages to stderr unless + * Log_destination permits. We don't do this until the postmaster is + * fully launched, since startup failures may as well be reported to + * stderr. + * + * If we are in fact disabling logging to stderr, first emit a log message + * saying so, to provide a breadcrumb trail for users who may not remember + * that their logging is configured to go somewhere else. + */ + if (!(Log_destination & LOG_DESTINATION_STDERR)) + ereport(LOG, + (errmsg("ending log output to stderr"), + errhint("Future log output will go to log destination \"%s\".", + Log_destination_string))); + + whereToSendOutput = DestNone; + + /* + * Report server startup in log. While we could emit this much earlier, + * it seems best to do so after starting the log collector, if we intend + * to use one. + */ ereport(LOG, (errmsg("starting %s", PG_VERSION_STR))); @@ -1172,51 +1278,13 @@ PostmasterMain(int argc, char *argv[]) if (!listen_addr_saved) AddToDataDirLockFile(LOCK_FILE_LINE_LISTEN_ADDR, ""); - /* - * Set up shared memory and semaphores. - */ - reset_shared(); - - /* - * Estimate number of openable files. This must happen after setting up - * semaphores, because on some platforms semaphores count as open files. - */ - set_max_safe_fds(); - - /* - * Set reference point for stack-depth checking. - */ - set_stack_base(); - - /* - * Initialize pipe (or process handle on Windows) that allows children to - * wake up from sleep on postmaster death. - */ - InitPostmasterDeathWatchHandle(); - -#ifdef WIN32 - - /* - * Initialize I/O completion port used to deliver list of dead children. - */ - win32ChildQueue = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1); - if (win32ChildQueue == NULL) - ereport(FATAL, - (errmsg("could not create I/O completion port for child queue"))); -#endif - /* * Record postmaster options. We delay this till now to avoid recording - * bogus options (eg, NBuffers too high for available memory). + * bogus options (eg, unusable port number). */ if (!CreateOptsFile(argc, argv, my_exec_path)) ExitPostmaster(1); -#ifdef EXEC_BACKEND - /* Write out nondefault GUC settings for child processes to use */ - write_nondefault_variables(PGC_POSTMASTER); -#endif - /* * Write the external PID file if requested */ @@ -1247,60 +1315,6 @@ PostmasterMain(int argc, char *argv[]) */ RemovePgTempFiles(); - /* - * Forcibly remove the files signaling a standby promotion request. - * Otherwise, the existence of those files triggers a promotion too early, - * whether a user wants that or not. - * - * This removal of files is usually unnecessary because they can exist - * only during a few moments during a standby promotion. However there is - * a race condition: if pg_ctl promote is executed and creates the files - * during a promotion, the files can stay around even after the server is - * brought up to new master. Then, if new standby starts by using the - * backup taken from that master, the files can exist at the server - * startup and should be removed in order to avoid an unexpected - * promotion. - * - * Note that promotion signal files need to be removed before the startup - * process is invoked. Because, after that, they can be used by - * postmaster's SIGUSR1 signal handler. - */ - RemovePromoteSignalFiles(); - - /* Do the same for logrotate signal file */ - RemoveLogrotateSignalFiles(); - - /* Remove any outdated file holding the current log filenames. */ - if (unlink(LOG_METAINFO_DATAFILE) < 0 && errno != ENOENT) - ereport(LOG, - (errcode_for_file_access(), - errmsg("could not remove file \"%s\": %m", - LOG_METAINFO_DATAFILE))); - - /* - * If enabled, start up syslogger collection subprocess - */ - SysLoggerPID = SysLogger_Start(); - - /* - * Reset whereToSendOutput from DestDebug (its starting state) to - * DestNone. This stops ereport from sending log messages to stderr unless - * Log_destination permits. We don't do this until the postmaster is - * fully launched, since startup failures may as well be reported to - * stderr. - * - * If we are in fact disabling logging to stderr, first emit a log message - * saying so, to provide a breadcrumb trail for users who may not remember - * that their logging is configured to go somewhere else. - */ - if (!(Log_destination & LOG_DESTINATION_STDERR)) - ereport(LOG, - (errmsg("ending log output to stderr"), - errhint("Future log output will go to log destination \"%s\".", - Log_destination_string))); - - whereToSendOutput = DestNone; - /* * Initialize stats collection subsystem (this does NOT start the * collector process!) diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index 2de2105105..25107e8a29 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -307,8 +307,6 @@ static int FreeDesc(AllocateDesc *desc); static void AtProcExit_Files(int code, Datum arg); static void CleanupTempFiles(bool isCommit, bool isProcExit); -static void RemovePgTempFilesInDir(const char *tmpdirname, bool missing_ok, - bool unlink_all); static void RemovePgTempRelationFiles(const char *tsdirname); static void RemovePgTempRelationFilesInDbspace(const char *dbspacedirname); @@ -2919,11 +2917,10 @@ RemovePgTempFiles(void) /* * In EXEC_BACKEND case there is a pgsql_tmp directory at the top level of - * DataDir as well. + * DataDir as well. However, that is *not* cleaned here because doing so + * would create a race condition. It's done separately, earlier in + * postmaster startup. */ -#ifdef EXEC_BACKEND - RemovePgTempFilesInDir(PG_TEMP_FILES_DIR, true, false); -#endif } /* @@ -2941,7 +2938,7 @@ RemovePgTempFiles(void) * (These two flags could be replaced by one, but it seems clearer to keep * them separate.) */ -static void +void RemovePgTempFilesInDir(const char *tmpdirname, bool missing_ok, bool unlink_all) { DIR *temp_dir; diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h index d2a8c52044..625fbc386a 100644 --- a/src/include/storage/fd.h +++ b/src/include/storage/fd.h @@ -135,6 +135,8 @@ extern void AtEOXact_Files(bool isCommit); extern void AtEOSubXact_Files(bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid); extern void RemovePgTempFiles(void); +extern void RemovePgTempFilesInDir(const char *tmpdirname, bool missing_ok, + bool unlink_all); extern bool looks_like_temp_rel_name(const char *name); extern int pg_fsync(int fd); diff --git a/src/include/utils/pidfile.h b/src/include/utils/pidfile.h index b2dcca64ac..21e7ccf92f 100644 --- a/src/include/utils/pidfile.h +++ b/src/include/utils/pidfile.h @@ -28,7 +28,8 @@ * * Lines 6 and up are added via AddToDataDirLockFile() after initial file * creation; also, line 5 is initially empty and is changed after the first - * Unix socket is opened. + * Unix socket is opened. Onlookers should not assume that lines 4 and up + * are filled in any particular order. * * Socket lock file(s), if used, have the same contents as lines 1-5, with * line 5 being their own directory.