From b99e4a04432aad2b885db60c8bc390bde79625ab Mon Sep 17 00:00:00 2001
From: Shlok Kyal <shlok.kyal.oss@gmail.com>
Date: Wed, 13 Mar 2024 16:52:28 +0530
Subject: [PATCH v28 5/5] Stop standby server if started by pg_createsubscriber

Stop standby server if it is started in pg_createsubscriber
---
 src/bin/pg_basebackup/pg_createsubscriber.c   | 43 +++++++++++--------
 .../t/040_pg_createsubscriber.pl              |  3 --
 2 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/src/bin/pg_basebackup/pg_createsubscriber.c b/src/bin/pg_basebackup/pg_createsubscriber.c
index c79ed9044c..7d78f4bac3 100644
--- a/src/bin/pg_basebackup/pg_createsubscriber.c
+++ b/src/bin/pg_basebackup/pg_createsubscriber.c
@@ -88,9 +88,9 @@ static void drop_replication_slot(PGconn *conn, struct LogicalRepInfo *dbinfo,
 								  const char *slot_name);
 static void pg_ctl_status(const char *pg_ctl_cmd, int rc);
 static void start_standby_server(struct CreateSubscriberOptions *opt,
-								 const char *pg_ctl_path, bool with_options);
-static void stop_standby_server(const char *pg_ctl_path, const char *datadir);
-static void wait_for_end_recovery(const char *conninfo, const char *pg_ctl_path,
+								 bool with_options);
+static void stop_standby_server(const char *datadir);
+static void wait_for_end_recovery(const char *conninfo,
 								  struct CreateSubscriberOptions *opt);
 static void create_publication(PGconn *conn, struct LogicalRepInfo *dbinfo);
 static void drop_publication(PGconn *conn, struct LogicalRepInfo *dbinfo);
@@ -114,6 +114,10 @@ static int	num_dbs = 0;
 
 static bool recovery_ended = false;
 
+static char *data_dir = NULL;
+static char *pg_ctl_path = NULL;
+static bool standby_server_started = false;
+
 enum WaitPMResult
 {
 	POSTMASTER_READY,
@@ -184,6 +188,10 @@ cleanup_objects_atexit(void)
 			}
 		}
 	}
+
+	/* stop the standby server if it is started in pg_createsubscriber */
+	if (standby_server_started)
+		stop_standby_server(data_dir);
 }
 
 static void
@@ -1231,8 +1239,7 @@ pg_ctl_status(const char *pg_ctl_cmd, int rc)
 }
 
 static void
-start_standby_server(struct CreateSubscriberOptions *opt, const char *pg_ctl_path,
-					 bool with_options)
+start_standby_server(struct CreateSubscriberOptions *opt, bool with_options)
 {
 	PQExpBuffer pg_ctl_cmd = createPQExpBuffer();
 	char		socket_string[MAXPGPATH + 200];
@@ -1267,10 +1274,11 @@ start_standby_server(struct CreateSubscriberOptions *opt, const char *pg_ctl_pat
 	pg_ctl_status(pg_ctl_cmd->data, rc);
 	destroyPQExpBuffer(pg_ctl_cmd);
 	pg_log_info("server was started");
+	standby_server_started = true;
 }
 
 static void
-stop_standby_server(const char *pg_ctl_path, const char *datadir)
+stop_standby_server(const char *datadir)
 {
 	char	   *pg_ctl_cmd;
 	int			rc;
@@ -1281,6 +1289,7 @@ stop_standby_server(const char *pg_ctl_path, const char *datadir)
 	rc = system(pg_ctl_cmd);
 	pg_ctl_status(pg_ctl_cmd, rc);
 	pg_log_info("server was stopped");
+	standby_server_started = false;
 }
 
 /*
@@ -1290,7 +1299,7 @@ stop_standby_server(const char *pg_ctl_path, const char *datadir)
  * the recovery process. By default, it waits forever.
  */
 static void
-wait_for_end_recovery(const char *conninfo, const char *pg_ctl_path,
+wait_for_end_recovery(const char *conninfo,
 					  struct CreateSubscriberOptions *opt)
 {
 	PGconn	   *conn;
@@ -1332,7 +1341,7 @@ wait_for_end_recovery(const char *conninfo, const char *pg_ctl_path,
 		{
 			if (++count > NUM_CONN_ATTEMPTS)
 			{
-				stop_standby_server(pg_ctl_path, opt->subscriber_dir);
+				stop_standby_server(opt->subscriber_dir);
 				pg_log_error("standby server disconnected from the primary");
 				break;
 			}
@@ -1345,7 +1354,7 @@ wait_for_end_recovery(const char *conninfo, const char *pg_ctl_path,
 		/* Bail out after recovery_timeout seconds if this option is set */
 		if (opt->recovery_timeout > 0 && timer >= opt->recovery_timeout)
 		{
-			stop_standby_server(pg_ctl_path, opt->subscriber_dir);
+			stop_standby_server(opt->subscriber_dir);
 			pg_log_error("recovery timed out");
 			disconnect_database(conn, true);
 		}
@@ -1665,7 +1674,6 @@ main(int argc, char **argv)
 	int			c;
 	int			option_index;
 
-	char	   *pg_ctl_path = NULL;
 	char	   *pg_resetwal_path = NULL;
 
 	char	   *pub_base_conninfo;
@@ -1745,6 +1753,7 @@ main(int argc, char **argv)
 			case 'D':
 				opt.subscriber_dir = pg_strdup(optarg);
 				canonicalize_path(opt.subscriber_dir);
+				data_dir = opt.subscriber_dir;
 				break;
 			case 'n':
 				dry_run = true;
@@ -1921,7 +1930,7 @@ main(int argc, char **argv)
 
 		pg_log_info("standby is up and running");
 		pg_log_info("stopping the server to start the transformation steps");
-		stop_standby_server(pg_ctl_path, opt.subscriber_dir);
+		stop_standby_server(opt.subscriber_dir);
 	}
 
 	/*
@@ -1930,7 +1939,7 @@ main(int argc, char **argv)
 	 * transformation steps.
 	 */
 	pg_log_info("starting the standby with command-line options");
-	start_standby_server(&opt, pg_ctl_path, true);
+	start_standby_server(&opt, true);
 
 	/* Check if the standby server is ready for logical replication */
 	check_subscriber(dbinfo);
@@ -1959,11 +1968,11 @@ main(int argc, char **argv)
 	 * until accepting connections.
 	 */
 	pg_log_info("stopping and starting the subscriber");
-	stop_standby_server(pg_ctl_path, opt.subscriber_dir);
-	start_standby_server(&opt, pg_ctl_path, true);
+	stop_standby_server(opt.subscriber_dir);
+	start_standby_server(&opt, true);
 
 	/* Waiting the subscriber to be promoted */
-	wait_for_end_recovery(dbinfo[0].subconninfo, pg_ctl_path, &opt);
+	wait_for_end_recovery(dbinfo[0].subconninfo, &opt);
 
 	/*
 	 * Create the subscription for each database on subscriber. It does not
@@ -1978,7 +1987,7 @@ main(int argc, char **argv)
 
 	/* Stop the subscriber */
 	pg_log_info("stopping the subscriber");
-	stop_standby_server(pg_ctl_path, opt.subscriber_dir);
+	stop_standby_server(opt.subscriber_dir);
 
 	/* Change system identifier from subscriber */
 	modify_subscriber_sysid(pg_resetwal_path, &opt);
@@ -1990,7 +1999,7 @@ main(int argc, char **argv)
 	 * the command-line options.
 	 */
 	if (dry_run)
-		start_standby_server(&opt, pg_ctl_path, false);
+		start_standby_server(&opt, false);
 
 	success = true;
 
diff --git a/src/bin/pg_basebackup/t/040_pg_createsubscriber.pl b/src/bin/pg_basebackup/t/040_pg_createsubscriber.pl
index 3bc4f3dc18..e7c5ccb577 100644
--- a/src/bin/pg_basebackup/t/040_pg_createsubscriber.pl
+++ b/src/bin/pg_basebackup/t/040_pg_createsubscriber.pl
@@ -105,9 +105,6 @@ command_fails(
 	],
 	'primary server is in recovery');
 
-# Stop node C
-$node_c->teardown_node;
-
 # Insert another row on node P and wait node S to catch up
 $node_p->safe_psql('pg1', "INSERT INTO tbl1 VALUES('second row')");
 $node_p->wait_for_replay_catchup($node_s);
-- 
2.34.1

