1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

postmaster: Move code to switch into FatalError state into function

There are two places switching to FatalError mode, behaving somewhat
differently. An upcoming commit will introduce a third. That doesn't seem seem
like a good idea.

This commit just moves the FatalError related code from HandleChildCrash()
into its own function, a subsequent commit will evolve the state machine
change to be suitable for other callers.

Reviewed-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Discussion: https://postgr.es/m/kgng5nrvnlv335evmsuvpnh354rw7qyazl73kdysev2cr2v5zu@m3cfzxicm5kp
This commit is contained in:
Andres Freund
2025-01-24 17:00:10 -05:00
parent f0b7ab7251
commit 8edd8c77c8

View File

@ -2673,6 +2673,55 @@ CleanupBackend(PMChild *bp,
LogChildExit(DEBUG2, procname, bp_pid, exitstatus);
}
/*
* Transition into FatalError state, in response to something bad having
* happened. Commonly the caller will have logged the reason for entering
* FatalError state.
*
* This should only be called when not already in FatalError or
* ImmediateShutdown state.
*/
static void
HandleFatalError(QuitSignalReason reason, bool consider_sigabrt)
{
int sigtosend;
Assert(!FatalError);
Assert(Shutdown != ImmediateShutdown);
SetQuitSignalReason(reason);
if (consider_sigabrt && send_abort_for_crash)
sigtosend = SIGABRT;
else
sigtosend = SIGQUIT;
/*
* Signal all other child processes to exit.
*
* We could exclude dead-end children here, but at least when sending
* SIGABRT it seems better to include them.
*/
TerminateChildren(sigtosend);
FatalError = true;
/* We now transit into a state of waiting for children to die */
if (pmState == PM_RECOVERY ||
pmState == PM_HOT_STANDBY ||
pmState == PM_RUN ||
pmState == PM_STOP_BACKENDS ||
pmState == PM_WAIT_XLOG_SHUTDOWN)
UpdatePMState(PM_WAIT_BACKENDS);
/*
* .. and if this doesn't happen quickly enough, now the clock is ticking
* for us to kill them without mercy.
*/
if (AbortStartTime == 0)
AbortStartTime = time(NULL);
}
/*
* HandleChildCrash -- cleanup after failed backend, bgwriter, checkpointer,
* walwriter, autovacuum, archiver, slot sync worker, or background worker.
@ -2698,33 +2747,12 @@ HandleChildCrash(int pid, int exitstatus, const char *procname)
LogChildExit(LOG, procname, pid, exitstatus);
ereport(LOG,
(errmsg("terminating any other active server processes")));
SetQuitSignalReason(PMQUIT_FOR_CRASH);
/*
* Signal all other child processes to exit. The crashed process has
* already been removed from ActiveChildList.
*
* We could exclude dead-end children here, but at least when sending
* SIGABRT it seems better to include them.
* Switch into error state. The crashed process has already been removed
* from ActiveChildList.
*/
TerminateChildren(send_abort_for_crash ? SIGABRT : SIGQUIT);
FatalError = true;
/* We now transit into a state of waiting for children to die */
if (pmState == PM_RECOVERY ||
pmState == PM_HOT_STANDBY ||
pmState == PM_RUN ||
pmState == PM_STOP_BACKENDS ||
pmState == PM_WAIT_XLOG_SHUTDOWN)
UpdatePMState(PM_WAIT_BACKENDS);
/*
* .. and if this doesn't happen quickly enough, now the clock is ticking
* for us to kill them without mercy.
*/
if (AbortStartTime == 0)
AbortStartTime = time(NULL);
HandleFatalError(PMQUIT_FOR_CRASH, true);
}
/*