Improve pg_ctl's message for shutdown after recovery.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 18 Jul 2024 17:48:58 +0000 (13:48 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 18 Jul 2024 17:48:58 +0000 (13:48 -0400)
If pg_ctl tries to start the postmaster, but the postmaster shuts down
because it completed a point-in-time recovery, pg_ctl used to report
a message that indicated a failure.  It's not really a failure, so
instead say "server shut down because of recovery target settings".

Zhao Junwang, Crisp Lee, Laurenz Albe

Discussion: https://postgr.es/m/CAGHPtV7GttPZ-HvxZuYRy70jLGQMEm5=LQc4fKGa=J74m2VZbg@mail.gmail.com

src/bin/pg_ctl/pg_ctl.c

index 57ed8c8e294f56a4de7b96eedcd47e03b0e6a62b..e7e878c22f04c3d4b3379004cb460e6d6db20e7a 100644 (file)
@@ -45,6 +45,7 @@ typedef enum
 {
        POSTMASTER_READY,
        POSTMASTER_STILL_STARTING,
+       POSTMASTER_SHUTDOWN_IN_RECOVERY,
        POSTMASTER_FAILED,
 } WaitPMResult;
 
@@ -657,17 +658,24 @@ wait_for_postmaster_start(pid_t pm_pid, bool do_checkpoint)
                 * On Windows, we may be checking the postmaster's parent shell, but
                 * that's fine for this purpose.
                 */
-#ifndef WIN32
                {
+                       bool            pm_died;
+#ifndef WIN32
                        int                     exitstatus;
 
-                       if (waitpid(pm_pid, &exitstatus, WNOHANG) == pm_pid)
-                               return POSTMASTER_FAILED;
-               }
+                       pm_died = (waitpid(pm_pid, &exitstatus, WNOHANG) == pm_pid);
 #else
-               if (WaitForSingleObject(postmasterProcess, 0) == WAIT_OBJECT_0)
-                       return POSTMASTER_FAILED;
+                       pm_died = (WaitForSingleObject(postmasterProcess, 0) == WAIT_OBJECT_0);
 #endif
+                       if (pm_died)
+                       {
+                               /* See if postmaster terminated intentionally */
+                               if (get_control_dbstate() == DB_SHUTDOWNED_IN_RECOVERY)
+                                       return POSTMASTER_SHUTDOWN_IN_RECOVERY;
+                               else
+                                       return POSTMASTER_FAILED;
+                       }
+               }
 
                /* Startup still in process; wait, printing a dot once per second */
                if (i % WAITS_PER_SEC == 0)
@@ -991,6 +999,10 @@ do_start(void)
                                                         progname);
                                exit(1);
                                break;
+                       case POSTMASTER_SHUTDOWN_IN_RECOVERY:
+                               print_msg(_(" done\n"));
+                               print_msg(_("server shut down because of recovery target settings\n"));
+                               break;
                        case POSTMASTER_FAILED:
                                print_msg(_(" stopped waiting\n"));
                                write_stderr(_("%s: could not start server\n"