aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/postmaster/postmaster.c202
-rw-r--r--src/backend/storage/file/fd.c11
-rw-r--r--src/include/storage/fd.h2
-rw-r--r--src/include/utils/pidfile.h3
4 files changed, 116 insertions, 102 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index a5446d54bb5..eb9e0221f88 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)));
@@ -1173,50 +1279,12 @@ PostmasterMain(int argc, char *argv[])
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
*/
@@ -1248,60 +1316,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 2de21051052..25107e8a290 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 d2a8c52044b..625fbc386a4 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 b2dcca64ac8..21e7ccf92fb 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.