postmaster: Move code to switch into FatalError state into function
authorAndres Freund <[email protected]>
Fri, 24 Jan 2025 22:00:10 +0000 (17:00 -0500)
committerAndres Freund <[email protected]>
Fri, 24 Jan 2025 22:00:10 +0000 (17:00 -0500)
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 <[email protected]>
Discussion: https://postgr.es/m/kgng5nrvnlv335evmsuvpnh354rw7qyazl73kdysev2cr2v5zu@m3cfzxicm5kp

src/backend/postmaster/postmaster.c

index a24c0385fe6fb6d49e41c4c943b139aff586b0a4..a92fe4240b28c6345e1b40d253f1220aef2375dc 100644 (file)
@@ -2674,40 +2674,35 @@ CleanupBackend(PMChild *bp,
 }
 
 /*
- * HandleChildCrash -- cleanup after failed backend, bgwriter, checkpointer,
- * walwriter, autovacuum, archiver, slot sync worker, or background worker.
+ * Transition into FatalError state, in response to something bad having
+ * happened. Commonly the caller will have logged the reason for entering
+ * FatalError state.
  *
- * The objectives here are to clean up our local state about the child
- * process, and to signal all other remaining children to quickdie.
- *
- * The caller has already released its PMChild slot.
+ * This should only be called when not already in FatalError or
+ * ImmediateShutdown state.
  */
 static void
-HandleChildCrash(int pid, int exitstatus, const char *procname)
+HandleFatalError(QuitSignalReason reason, bool consider_sigabrt)
 {
-   /*
-    * We only log messages and send signals if this is the first process
-    * crash and we're not doing an immediate shutdown; otherwise, we're only
-    * here to update postmaster's idea of live processes.  If we have already
-    * signaled children, nonzero exit status is to be expected, so don't
-    * clutter log.
-    */
-   if (FatalError || Shutdown == ImmediateShutdown)
-       return;
+   int         sigtosend;
 
-   LogChildExit(LOG, procname, pid, exitstatus);
-   ereport(LOG,
-           (errmsg("terminating any other active server processes")));
-   SetQuitSignalReason(PMQUIT_FOR_CRASH);
+   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.  The crashed process has
-    * already been removed from ActiveChildList.
+    * 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(send_abort_for_crash ? SIGABRT : SIGQUIT);
+   TerminateChildren(sigtosend);
 
    FatalError = true;
 
@@ -2727,6 +2722,39 @@ HandleChildCrash(int pid, int exitstatus, const char *procname)
        AbortStartTime = time(NULL);
 }
 
+/*
+ * HandleChildCrash -- cleanup after failed backend, bgwriter, checkpointer,
+ * walwriter, autovacuum, archiver, slot sync worker, or background worker.
+ *
+ * The objectives here are to clean up our local state about the child
+ * process, and to signal all other remaining children to quickdie.
+ *
+ * The caller has already released its PMChild slot.
+ */
+static void
+HandleChildCrash(int pid, int exitstatus, const char *procname)
+{
+   /*
+    * We only log messages and send signals if this is the first process
+    * crash and we're not doing an immediate shutdown; otherwise, we're only
+    * here to update postmaster's idea of live processes.  If we have already
+    * signaled children, nonzero exit status is to be expected, so don't
+    * clutter log.
+    */
+   if (FatalError || Shutdown == ImmediateShutdown)
+       return;
+
+   LogChildExit(LOG, procname, pid, exitstatus);
+   ereport(LOG,
+           (errmsg("terminating any other active server processes")));
+
+   /*
+    * Switch into error state. The crashed process has already been removed
+    * from ActiveChildList.
+    */
+   HandleFatalError(PMQUIT_FOR_CRASH, true);
+}
+
 /*
  * Log the death of a child process.
  */