static int CountChildren(int target);
static Backend *assign_backendlist_entry(void);
+static void LaunchMissingBackgroundProcesses(void);
static void maybe_start_bgworkers(void);
static bool CreateOptsFile(int argc, char *argv[], char *fullprogname);
static pid_t StartChildProcess(BackendType type);
static void StartAutovacuumWorker(void);
-static void MaybeStartWalReceiver(void);
-static void MaybeStartWalSummarizer(void);
static void InitPostmasterDeathWatchHandle(void);
-static void MaybeStartSlotSyncWorker(void);
-
-/*
- * Archiver is allowed to start up at the current postmaster state?
- *
- * If WAL archiving is enabled always, we are allowed to start archiver
- * even during recovery.
- */
-#define PgArchStartupAllowed() \
- (((XLogArchivingActive() && pmState == PM_RUN) || \
- (XLogArchivingAlways() && \
- (pmState == PM_RECOVERY || pmState == PM_HOT_STANDBY))) && \
- PgArchCanRestart())
#ifdef WIN32
#define WNOHANG 0 /* ignored, so any integer value will do */
}
}
- /* If we have lost the log collector, try to start a new one */
- if (SysLoggerPID == 0 && Logging_collector)
- SysLoggerPID = SysLogger_Start();
-
- /*
- * If no background writer process is running, and we are not in a
- * state that prevents it, start one. It doesn't matter if this
- * fails, we'll just try again later. Likewise for the checkpointer.
- */
- if (pmState == PM_RUN || pmState == PM_RECOVERY ||
- pmState == PM_HOT_STANDBY || pmState == PM_STARTUP)
- {
- if (CheckpointerPID == 0)
- CheckpointerPID = StartChildProcess(B_CHECKPOINTER);
- if (BgWriterPID == 0)
- BgWriterPID = StartChildProcess(B_BG_WRITER);
- }
-
/*
- * Likewise, if we have lost the walwriter process, try to start a new
- * one. But this is needed only in normal operation (else we cannot
- * be writing any new WAL).
+ * If we need to launch any background processes after changing state
+ * or because some exited, do so now.
*/
- if (WalWriterPID == 0 && pmState == PM_RUN)
- WalWriterPID = StartChildProcess(B_WAL_WRITER);
-
- /*
- * If we have lost the autovacuum launcher, try to start a new one. We
- * don't want autovacuum to run in binary upgrade mode because
- * autovacuum might update relfrozenxid for empty tables before the
- * physical files are put in place.
- */
- if (!IsBinaryUpgrade && AutoVacPID == 0 &&
- (AutoVacuumingActive() || start_autovac_launcher) &&
- pmState == PM_RUN)
- {
- AutoVacPID = StartChildProcess(B_AUTOVAC_LAUNCHER);
- if (AutoVacPID != 0)
- start_autovac_launcher = false; /* signal processed */
- }
-
- /* If we have lost the archiver, try to start a new one. */
- if (PgArchPID == 0 && PgArchStartupAllowed())
- PgArchPID = StartChildProcess(B_ARCHIVER);
-
- /* If we need to start a slot sync worker, try to do that now */
- MaybeStartSlotSyncWorker();
+ LaunchMissingBackgroundProcesses();
/* If we need to signal the autovacuum launcher, do so now */
if (avlauncher_needs_signal)
kill(AutoVacPID, SIGUSR2);
}
- /* If we need to start a WAL receiver, try to do that now */
- if (WalReceiverRequested)
- MaybeStartWalReceiver();
-
- /* If we need to start a WAL summarizer, try to do that now */
- MaybeStartWalSummarizer();
-
- /* Get other worker processes running, if needed */
- if (StartWorkerNeeded || HaveCrashedWorker)
- maybe_start_bgworkers();
-
#ifdef HAVE_PTHREAD_IS_THREADED_NP
/*
connsAllowed = true;
/*
- * Crank up any background tasks that we didn't start earlier
- * already. It doesn't matter if any of these fail, we'll just
- * try again later.
+ * At the next iteration of the postmaster's main loop, we will
+ * crank up the background tasks like the autovacuum launcher and
+ * background workers that were not started earlier already.
*/
- if (CheckpointerPID == 0)
- CheckpointerPID = StartChildProcess(B_CHECKPOINTER);
- if (BgWriterPID == 0)
- BgWriterPID = StartChildProcess(B_BG_WRITER);
- if (WalWriterPID == 0)
- WalWriterPID = StartChildProcess(B_WAL_WRITER);
- MaybeStartWalSummarizer();
- if (!IsBinaryUpgrade && AutoVacuumingActive() && AutoVacPID == 0)
- AutoVacPID = StartChildProcess(B_AUTOVAC_LAUNCHER);
- if (PgArchStartupAllowed() && PgArchPID == 0)
- PgArchPID = StartChildProcess(B_ARCHIVER);
- MaybeStartSlotSyncWorker();
- maybe_start_bgworkers();
+ StartWorkerNeeded = true;
/* at this point we are really open for business */
ereport(LOG,
/*
* Was it the archiver? If exit status is zero (normal) or one (FATAL
* exit), we assume everything is all right just like normal backends
- * and just try to restart a new one so that we immediately retry
- * archiving remaining files. (If fail, we'll try again in future
- * cycles of the postmaster's main loop.) Unless we were waiting for
- * it to shut down; don't restart it in that case, and
- * PostmasterStateMachine() will advance to the next shutdown step.
+ * and just try to start a new one on the next cycle of the
+ * postmaster's main loop, to retry archiving remaining files.
*/
if (pid == PgArchPID)
{
if (!EXIT_STATUS_0(exitstatus) && !EXIT_STATUS_1(exitstatus))
HandleChildCrash(pid, exitstatus,
_("archiver process"));
- if (PgArchStartupAllowed())
- PgArchPID = StartChildProcess(B_ARCHIVER);
continue;
}
}
}
+/*
+ * Launch background processes after state change, or relaunch after an
+ * existing process has exited.
+ *
+ * Check the current pmState and the status of any background processes. If
+ * there are any background processes missing that should be running in the
+ * current state, but are not, launch them.
+ */
+static void
+LaunchMissingBackgroundProcesses(void)
+{
+ /* Syslogger is active in all states */
+ if (SysLoggerPID == 0 && Logging_collector)
+ SysLoggerPID = SysLogger_Start();
+
+ /*
+ * The checkpointer and the background writer are active from the start,
+ * until shutdown is initiated.
+ *
+ * (If the checkpointer is not running when we enter the the PM_SHUTDOWN
+ * state, it is launched one more time to perform the shutdown checkpoint.
+ * That's done in PostmasterStateMachine(), not here.)
+ */
+ if (pmState == PM_RUN || pmState == PM_RECOVERY ||
+ pmState == PM_HOT_STANDBY || pmState == PM_STARTUP)
+ {
+ if (CheckpointerPID == 0)
+ CheckpointerPID = StartChildProcess(B_CHECKPOINTER);
+ if (BgWriterPID == 0)
+ BgWriterPID = StartChildProcess(B_BG_WRITER);
+ }
+
+ /*
+ * WAL writer is needed only in normal operation (else we cannot be
+ * writing any new WAL).
+ */
+ if (WalWriterPID == 0 && pmState == PM_RUN)
+ WalWriterPID = StartChildProcess(B_WAL_WRITER);
+
+ /*
+ * We don't want autovacuum to run in binary upgrade mode because
+ * autovacuum might update relfrozenxid for empty tables before the
+ * physical files are put in place.
+ */
+ if (!IsBinaryUpgrade && AutoVacPID == 0 &&
+ (AutoVacuumingActive() || start_autovac_launcher) &&
+ pmState == PM_RUN)
+ {
+ AutoVacPID = StartChildProcess(B_AUTOVAC_LAUNCHER);
+ if (AutoVacPID != 0)
+ start_autovac_launcher = false; /* signal processed */
+ }
+
+ /*
+ * If WAL archiving is enabled always, we are allowed to start archiver
+ * even during recovery.
+ */
+ if (PgArchPID == 0 &&
+ ((XLogArchivingActive() && pmState == PM_RUN) ||
+ (XLogArchivingAlways() && (pmState == PM_RECOVERY || pmState == PM_HOT_STANDBY))) &&
+ PgArchCanRestart())
+ PgArchPID = StartChildProcess(B_ARCHIVER);
+
+ /*
+ * If we need to start a slot sync worker, try to do that now
+ *
+ * We allow to start the slot sync worker when we are on a hot standby,
+ * fast or immediate shutdown is not in progress, slot sync parameters are
+ * configured correctly, and it is the first time of worker's launch, or
+ * enough time has passed since the worker was launched last.
+ */
+ if (SlotSyncWorkerPID == 0 && pmState == PM_HOT_STANDBY &&
+ Shutdown <= SmartShutdown && sync_replication_slots &&
+ ValidateSlotSyncParams(LOG) && SlotSyncWorkerCanRestart())
+ SlotSyncWorkerPID = StartChildProcess(B_SLOTSYNC_WORKER);
+
+ /*
+ * If we need to start a WAL receiver, try to do that now
+ *
+ * Note: if WalReceiverPID is already nonzero, it might seem that we
+ * should clear WalReceiverRequested. However, there's a race condition
+ * if the walreceiver terminates and the startup process immediately
+ * requests a new one: it's quite possible to get the signal for the
+ * request before reaping the dead walreceiver process. Better to risk
+ * launching an extra walreceiver than to miss launching one we need. (The
+ * walreceiver code has logic to recognize that it should go away if not
+ * needed.)
+ */
+ if (WalReceiverRequested)
+ {
+ if (WalReceiverPID == 0 &&
+ (pmState == PM_STARTUP || pmState == PM_RECOVERY ||
+ pmState == PM_HOT_STANDBY) &&
+ Shutdown <= SmartShutdown)
+ {
+ WalReceiverPID = StartChildProcess(B_WAL_RECEIVER);
+ if (WalReceiverPID != 0)
+ WalReceiverRequested = false;
+ /* else leave the flag set, so we'll try again later */
+ }
+ }
+
+ /* If we need to start a WAL summarizer, try to do that now */
+ if (summarize_wal && WalSummarizerPID == 0 &&
+ (pmState == PM_RUN || pmState == PM_HOT_STANDBY) &&
+ Shutdown <= SmartShutdown)
+ WalSummarizerPID = StartChildProcess(B_WAL_SUMMARIZER);
+
+ /* Get other worker processes running, if needed */
+ if (StartWorkerNeeded || HaveCrashedWorker)
+ maybe_start_bgworkers();
+}
/*
* Send a signal to a postmaster child process
StartWorkerNeeded = true;
}
- if (StartWorkerNeeded || HaveCrashedWorker)
- maybe_start_bgworkers();
-
/* Tell syslogger to rotate logfile if requested */
if (SysLoggerPID != 0)
{
if (CheckPostmasterSignal(PMSIGNAL_START_WALRECEIVER))
{
/* Startup Process wants us to start the walreceiver process. */
- /* Start immediately if possible, else remember request for later. */
WalReceiverRequested = true;
- MaybeStartWalReceiver();
}
/*
}
}
-/*
- * MaybeStartWalReceiver
- * Start the WAL receiver process, if not running and our state allows.
- *
- * Note: if WalReceiverPID is already nonzero, it might seem that we should
- * clear WalReceiverRequested. However, there's a race condition if the
- * walreceiver terminates and the startup process immediately requests a new
- * one: it's quite possible to get the signal for the request before reaping
- * the dead walreceiver process. Better to risk launching an extra
- * walreceiver than to miss launching one we need. (The walreceiver code
- * has logic to recognize that it should go away if not needed.)
- */
-static void
-MaybeStartWalReceiver(void)
-{
- if (WalReceiverPID == 0 &&
- (pmState == PM_STARTUP || pmState == PM_RECOVERY ||
- pmState == PM_HOT_STANDBY) &&
- Shutdown <= SmartShutdown)
- {
- WalReceiverPID = StartChildProcess(B_WAL_RECEIVER);
- if (WalReceiverPID != 0)
- WalReceiverRequested = false;
- /* else leave the flag set, so we'll try again later */
- }
-}
-
-/*
- * MaybeStartWalSummarizer
- * Start the WAL summarizer process, if not running and our state allows.
- */
-static void
-MaybeStartWalSummarizer(void)
-{
- if (summarize_wal && WalSummarizerPID == 0 &&
- (pmState == PM_RUN || pmState == PM_HOT_STANDBY) &&
- Shutdown <= SmartShutdown)
- WalSummarizerPID = StartChildProcess(B_WAL_SUMMARIZER);
-}
-
-
-/*
- * MaybeStartSlotSyncWorker
- * Start the slot sync worker, if not running and our state allows.
- *
- * We allow to start the slot sync worker when we are on a hot standby,
- * fast or immediate shutdown is not in progress, slot sync parameters
- * are configured correctly, and it is the first time of worker's launch,
- * or enough time has passed since the worker was launched last.
- */
-static void
-MaybeStartSlotSyncWorker(void)
-{
- if (SlotSyncWorkerPID == 0 && pmState == PM_HOT_STANDBY &&
- Shutdown <= SmartShutdown && sync_replication_slots &&
- ValidateSlotSyncParams(LOG) && SlotSyncWorkerCanRestart())
- SlotSyncWorkerPID = StartChildProcess(B_SLOTSYNC_WORKER);
-}
/*
* Create the opts file