Skip to content

Commit 8af60da

Browse files
committed
Don't launch new child processes after we've been told to shut down.
Once we've received a shutdown signal (SIGINT or SIGTERM), we should not launch any more child processes, even if we get signals requesting such. The normal code path for spawning backends has always understood that, but the postmaster's infrastructure for hot standby and autovacuum didn't get the memo. As reported by Hari Babu in bug #7643, this could lead to failure to shut down at all in some cases, such as when SIGINT is received just before the startup process sends PMSIGNAL_RECOVERY_STARTED: we'd launch a bgwriter and checkpointer, and then those processes would have no idea that they ought to quit. Similarly, launching a new autovacuum worker would result in waiting till it finished before shutting down. Also, switch the order of the code blocks in reaper() that detect startup process crash versus shutdown termination. Once we've sent it a signal, we should not consider that exit(1) is surprising. This is just a cosmetic fix since shutdown occurs correctly anyway, but better not to log a phony complaint about startup process crash. Back-patch to 9.0. Some parts of this might be applicable before that, but given the lack of prior complaints I'm not going to worry too much about older branches.
1 parent 278b605 commit 8af60da

File tree

1 file changed

+23
-20
lines changed

1 file changed

+23
-20
lines changed

src/backend/postmaster/postmaster.c

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2195,9 +2195,9 @@ pmdie(SIGNAL_ARGS)
21952195
if (pmState == PM_RECOVERY)
21962196
{
21972197
/*
2198-
* Only startup, bgwriter, and checkpointer should be active
2199-
* in this state; we just signaled the first two, and we don't
2200-
* want to kill checkpointer yet.
2198+
* Only startup, bgwriter, walreceiver, and/or checkpointer
2199+
* should be active in this state; we just signaled the first
2200+
* three, and we don't want to kill checkpointer yet.
22012201
*/
22022202
pmState = PM_WAIT_BACKENDS;
22032203
}
@@ -2308,6 +2308,18 @@ reaper(SIGNAL_ARGS)
23082308
{
23092309
StartupPID = 0;
23102310

2311+
/*
2312+
* Startup process exited in response to a shutdown request (or it
2313+
* completed normally regardless of the shutdown request).
2314+
*/
2315+
if (Shutdown > NoShutdown &&
2316+
(EXIT_STATUS_0(exitstatus) || EXIT_STATUS_1(exitstatus)))
2317+
{
2318+
pmState = PM_WAIT_BACKENDS;
2319+
/* PostmasterStateMachine logic does the rest */
2320+
continue;
2321+
}
2322+
23112323
/*
23122324
* Unexpected exit of startup process (including FATAL exit)
23132325
* during PM_STARTUP is treated as catastrophic. There are no
@@ -2322,18 +2334,6 @@ reaper(SIGNAL_ARGS)
23222334
ExitPostmaster(1);
23232335
}
23242336

2325-
/*
2326-
* Startup process exited in response to a shutdown request (or it
2327-
* completed normally regardless of the shutdown request).
2328-
*/
2329-
if (Shutdown > NoShutdown &&
2330-
(EXIT_STATUS_0(exitstatus) || EXIT_STATUS_1(exitstatus)))
2331-
{
2332-
pmState = PM_WAIT_BACKENDS;
2333-
/* PostmasterStateMachine logic does the rest */
2334-
continue;
2335-
}
2336-
23372337
/*
23382338
* After PM_STARTUP, any unexpected exit (including FATAL exit) of
23392339
* the startup process is catastrophic, so kill other children,
@@ -4243,7 +4243,7 @@ sigusr1_handler(SIGNAL_ARGS)
42434243
* first. We don't want to go back to recovery in that case.
42444244
*/
42454245
if (CheckPostmasterSignal(PMSIGNAL_RECOVERY_STARTED) &&
4246-
pmState == PM_STARTUP)
4246+
pmState == PM_STARTUP && Shutdown == NoShutdown)
42474247
{
42484248
/* WAL redo has started. We're out of reinitialization. */
42494249
FatalError = false;
@@ -4260,7 +4260,7 @@ sigusr1_handler(SIGNAL_ARGS)
42604260
pmState = PM_RECOVERY;
42614261
}
42624262
if (CheckPostmasterSignal(PMSIGNAL_BEGIN_HOT_STANDBY) &&
4263-
pmState == PM_RECOVERY)
4263+
pmState == PM_RECOVERY && Shutdown == NoShutdown)
42644264
{
42654265
/*
42664266
* Likewise, start other special children as needed.
@@ -4291,7 +4291,8 @@ sigusr1_handler(SIGNAL_ARGS)
42914291
signal_child(SysLoggerPID, SIGUSR1);
42924292
}
42934293

4294-
if (CheckPostmasterSignal(PMSIGNAL_START_AUTOVAC_LAUNCHER))
4294+
if (CheckPostmasterSignal(PMSIGNAL_START_AUTOVAC_LAUNCHER) &&
4295+
Shutdown == NoShutdown)
42954296
{
42964297
/*
42974298
* Start one iteration of the autovacuum daemon, even if autovacuuming
@@ -4305,7 +4306,8 @@ sigusr1_handler(SIGNAL_ARGS)
43054306
start_autovac_launcher = true;
43064307
}
43074308

4308-
if (CheckPostmasterSignal(PMSIGNAL_START_AUTOVAC_WORKER))
4309+
if (CheckPostmasterSignal(PMSIGNAL_START_AUTOVAC_WORKER) &&
4310+
Shutdown == NoShutdown)
43094311
{
43104312
/* The autovacuum launcher wants us to start a worker process. */
43114313
StartAutovacuumWorker();
@@ -4314,7 +4316,8 @@ sigusr1_handler(SIGNAL_ARGS)
43144316
if (CheckPostmasterSignal(PMSIGNAL_START_WALRECEIVER) &&
43154317
WalReceiverPID == 0 &&
43164318
(pmState == PM_STARTUP || pmState == PM_RECOVERY ||
4317-
pmState == PM_HOT_STANDBY || pmState == PM_WAIT_READONLY))
4319+
pmState == PM_HOT_STANDBY || pmState == PM_WAIT_READONLY) &&
4320+
Shutdown == NoShutdown)
43184321
{
43194322
/* Startup Process wants us to start the walreceiver process. */
43204323
WalReceiverPID = StartWalReceiver();

0 commit comments

Comments
 (0)