* hot standby during archive recovery.
*
* When the startup process is ready to start archive recovery, it signals the
- * postmaster, and we switch to PM_RECOVERY state. The background writer is
- * launched, while the startup process continues applying WAL. If Hot Standby
- * is enabled, then, after reaching a consistent point in WAL redo, startup
- * process signals us again, and we switch to PM_HOT_STANDBY state and
- * begin accepting connections to perform read-only queries. When archive
- * recovery is finished, the startup process exits with exit code 0 and we
- * switch to PM_RUN state.
+ * postmaster, and we switch to PM_RECOVERY state. The background writer and
+ * checkpointer are launched, while the startup process continues applying WAL.
+ * If Hot Standby is enabled, then, after reaching a consistent point in WAL
+ * redo, startup process signals us again, and we switch to PM_HOT_STANDBY
+ * state and begin accepting connections to perform read-only queries. When
+ * archive recovery is finished, the startup process exits with exit code 0
+ * and we switch to PM_RUN state.
*
* Normal child backends can only be launched when we are in PM_RUN or
* PM_HOT_STANDBY state. (We also allow launch of normal
* handling setup of child processes. See tcop/postgres.c,
* bootstrap/bootstrap.c, postmaster/bgwriter.c, postmaster/walwriter.c,
* postmaster/autovacuum.c, postmaster/pgarch.c, postmaster/pgstat.c,
- * postmaster/syslogger.c and postmaster/checkpointer.c
+ * postmaster/syslogger.c and postmaster/checkpointer.c.
*/
pqinitmask();
PG_SETMASK(&BlockSig);
/*
* 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.
+ * fails, we'll just try again later. Likewise for the checkpointer.
*/
if (pmState == PM_RUN || pmState == PM_RECOVERY ||
- pmState == PM_HOT_STANDBY)
+ pmState == PM_HOT_STANDBY)
{
if (BgWriterPID == 0)
BgWriterPID = StartBackgroundWriter();
/*
* Likewise, if we have lost the walwriter process, try to start a new
- * one.
+ * one. But this is needed only in normal operation (else we cannot
+ * be writing any new WAL).
*/
if (WalWriterPID == 0 && pmState == PM_RUN)
WalWriterPID = StartWalWriter();
/* and the autovac launcher too */
if (AutoVacPID != 0)
signal_child(AutoVacPID, SIGTERM);
+ /* and the bgwriter too */
+ if (BgWriterPID != 0)
+ signal_child(BgWriterPID, SIGTERM);
/* and the walwriter too */
if (WalWriterPID != 0)
signal_child(WalWriterPID, SIGTERM);
- if (BgWriterPID != 0)
- signal_child(BgWriterPID, SIGTERM);
/*
* If we're in recovery, we can't kill the startup process
if (StartupPID != 0)
signal_child(StartupPID, SIGTERM);
- if (WalReceiverPID != 0)
- signal_child(WalReceiverPID, SIGTERM);
if (BgWriterPID != 0)
signal_child(BgWriterPID, SIGTERM);
+ if (WalReceiverPID != 0)
+ signal_child(WalReceiverPID, SIGTERM);
if (pmState == PM_RECOVERY)
{
- /* only checkpointer is active in this state */
+ /*
+ * Only startup, bgwriter, and checkpointer should be active
+ * in this state; we just signaled the first two, and we don't
+ * want to kill checkpointer yet.
+ */
pmState = PM_WAIT_BACKENDS;
}
else if (pmState == PM_RUN ||
}
/*
- * Crank up background tasks, if we didn't do that already
+ * Crank up the background tasks, if we didn't do that already
* when we entered consistent recovery state. It doesn't matter
* if this fails, we'll just try again later.
*/
BgWriterPID = StartBackgroundWriter();
if (CheckpointerPID == 0)
CheckpointerPID = StartCheckpointer();
+ if (WalWriterPID == 0)
+ WalWriterPID = StartWalWriter();
/*
* Likewise, start other special children as needed. In a restart
* situation, some of them may be alive already.
*/
- if (WalWriterPID == 0)
- WalWriterPID = StartWalWriter();
if (!IsBinaryUpgrade && AutoVacuumingActive() && AutoVacPID == 0)
AutoVacPID = StartAutoVacLauncher();
if (XLogArchivingActive() && PgArchPID == 0)
}
/*
- * Was it the bgwriter?
+ * Was it the bgwriter? Normal exit can be ignored; we'll start a
+ * new one at the next iteration of the postmaster's main loop, if
+ * necessary. Any other exit condition is treated as a crash.
*/
if (pid == BgWriterPID)
{
FatalError = false;
/*
- * Crank up the background writers. It doesn't matter if this fails,
+ * Crank up the background tasks. It doesn't matter if this fails,
* we'll just try again later.
*/
- Assert(CheckpointerPID == 0);
- CheckpointerPID = StartCheckpointer();
Assert(BgWriterPID == 0);
BgWriterPID = StartBackgroundWriter();
+ Assert(CheckpointerPID == 0);
+ CheckpointerPID = StartCheckpointer();
pmState = PM_RECOVERY;
}