From f0d0098a1ffbd7a319db6e37329dd9b7e2588d3f Mon Sep 17 00:00:00 2001
From: Zhao Junwang <zhjwpku@gmail.com>
Date: Thu, 9 Nov 2023 15:03:38 +0800
Subject: [PATCH v5] PITR shutdown should not report error by pg_ctl

After a PITR recovery, the dbstate in pg_control is
DB_SHUTDOWNED_IN_RECOVERY, check this and do not report error
in pg_ctl.

Signed-off-by: Zhao Junwang <zhjwpku@gmail.com>
---
 src/bin/pg_ctl/pg_ctl.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index 6900b27675..22c4bbc71b 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -45,6 +45,11 @@ typedef enum
 {
 	POSTMASTER_READY,
 	POSTMASTER_STILL_STARTING,
+	/*
+	 * postmaster no longer running, because it stopped after recovery
+	 * completed.
+	 */
+	POSTMASTER_SHUTDOWN_IN_RECOVERY,
 	POSTMASTER_FAILED,
 } WaitPMResult;
 
@@ -662,11 +667,21 @@ wait_for_postmaster_start(pid_t pm_pid, bool do_checkpoint)
 			int			exitstatus;
 
 			if (waitpid(pm_pid, &exitstatus, WNOHANG) == pm_pid)
-				return POSTMASTER_FAILED;
+			{
+				if (get_control_dbstate() == DB_SHUTDOWNED_IN_RECOVERY)
+					return POSTMASTER_SHUTDOWN_IN_RECOVERY;
+				else
+					return POSTMASTER_FAILED;
+			}
 		}
 #else
 		if (WaitForSingleObject(postmasterProcess, 0) == WAIT_OBJECT_0)
-			return POSTMASTER_FAILED;
+		{
+			if (get_control_dbstate() == DB_SHUTDOWNED_IN_RECOVERY)
+				return POSTMASTER_SHUTDOWN_IN_RECOVERY;
+			else
+				return POSTMASTER_FAILED;
+		}
 #endif
 
 		/* Startup still in process; wait, printing a dot once per second */
@@ -991,6 +1006,10 @@ do_start(void)
 							 progname);
 				exit(1);
 				break;
+			case POSTMASTER_SHUTDOWN_IN_RECOVERY:
+				print_msg(_(" done, automatically shut down after recovery\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"
-- 
2.41.0

