]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
postmaster: Move code to switch into FatalError state into function
authorAndres Freund <andres@anarazel.de>
Fri, 24 Jan 2025 22:00:10 +0000 (17:00 -0500)
committerAndres Freund <andres@anarazel.de>
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 <bertranddrouvot.pg@gmail.com>
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.
  */