From 3830d0e89293d6f8a87fe5facc9c2c64209a2e3e Mon Sep 17 00:00:00 2001
From: Asif Rehman <asif.rehman@highgo.ca>
Date: Wed, 30 Oct 2019 10:21:38 +0500
Subject: [PATCH 1/7] removed PG_ENSURE_ERROR_CLEANUP macro from basebackup,
 instead registered base_backup_cleanup with before_shmem_exit handler. This
 will make sure that cleanup is always done when wal sender exits.

---
 src/backend/replication/basebackup.c | 182 +++++++++++++--------------
 1 file changed, 90 insertions(+), 92 deletions(-)

diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index 1fa4551eff..ea87676405 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -243,6 +243,8 @@ perform_base_backup(basebackup_options *opt)
 	StringInfo	tblspc_map_file = NULL;
 	int			datadirpathlen;
 	List	   *tablespaces = NIL;
+	ListCell   *lc;
+	tablespaceinfo *ti;
 
 	datadirpathlen = strlen(DataDir);
 
@@ -261,121 +263,117 @@ perform_base_backup(basebackup_options *opt)
 	/*
 	 * Once do_pg_start_backup has been called, ensure that any failure causes
 	 * us to abort the backup so we don't "leak" a backup counter. For this
-	 * reason, *all* functionality between do_pg_start_backup() and the end of
-	 * do_pg_stop_backup() should be inside the error cleanup block!
+	 * reason, register base_backup_cleanup with before_shmem_exit handler.
+	 * This will make sure that call is always made when process exits. In
+	 * success, do_pg_stop_backup will have taken the system out of backup
+	 * mode and this callback will have no effect, Otherwise the required
+	 * cleanup will be done in any case.
 	 */
+	before_shmem_exit(base_backup_cleanup, (Datum) 0);
 
-	PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
-	{
-		ListCell   *lc;
-		tablespaceinfo *ti;
-
-		SendXlogRecPtrResult(startptr, starttli);
+	SendXlogRecPtrResult(startptr, starttli);
 
-		/*
-		 * Calculate the relative path of temporary statistics directory in
-		 * order to skip the files which are located in that directory later.
-		 */
-		if (is_absolute_path(pgstat_stat_directory) &&
-			strncmp(pgstat_stat_directory, DataDir, datadirpathlen) == 0)
-			statrelpath = psprintf("./%s", pgstat_stat_directory + datadirpathlen + 1);
-		else if (strncmp(pgstat_stat_directory, "./", 2) != 0)
-			statrelpath = psprintf("./%s", pgstat_stat_directory);
-		else
-			statrelpath = pgstat_stat_directory;
-
-		/* Add a node for the base directory at the end */
-		ti = palloc0(sizeof(tablespaceinfo));
-		ti->size = opt->progress ? sendDir(".", 1, true, tablespaces, true) : -1;
-		tablespaces = lappend(tablespaces, ti);
+	/*
+	 * Calculate the relative path of temporary statistics directory in order
+	 * to skip the files which are located in that directory later.
+	 */
+	if (is_absolute_path(pgstat_stat_directory) &&
+		strncmp(pgstat_stat_directory, DataDir, datadirpathlen) == 0)
+		statrelpath = psprintf("./%s", pgstat_stat_directory + datadirpathlen + 1);
+	else if (strncmp(pgstat_stat_directory, "./", 2) != 0)
+		statrelpath = psprintf("./%s", pgstat_stat_directory);
+	else
+		statrelpath = pgstat_stat_directory;
 
-		/* Send tablespace header */
-		SendBackupHeader(tablespaces);
+	/* Add a node for the base directory at the end */
+	ti = palloc0(sizeof(tablespaceinfo));
+	ti->size = opt->progress ? sendDir(".", 1, true, tablespaces, true) : -1;
+	tablespaces = lappend(tablespaces, ti);
 
-		/* Setup and activate network throttling, if client requested it */
-		if (opt->maxrate > 0)
-		{
-			throttling_sample =
-				(int64) opt->maxrate * (int64) 1024 / THROTTLING_FREQUENCY;
+	/* Send tablespace header */
+	SendBackupHeader(tablespaces);
 
-			/*
-			 * The minimum amount of time for throttling_sample bytes to be
-			 * transferred.
-			 */
-			elapsed_min_unit = USECS_PER_SEC / THROTTLING_FREQUENCY;
-
-			/* Enable throttling. */
-			throttling_counter = 0;
+	/* Setup and activate network throttling, if client requested it */
+	if (opt->maxrate > 0)
+	{
+		throttling_sample =
+			(int64) opt->maxrate * (int64) 1024 / THROTTLING_FREQUENCY;
 
-			/* The 'real data' starts now (header was ignored). */
-			throttled_last = GetCurrentTimestamp();
-		}
-		else
-		{
-			/* Disable throttling. */
-			throttling_counter = -1;
-		}
+		/*
+		 * The minimum amount of time for throttling_sample bytes to be
+		 * transferred.
+		 */
+		elapsed_min_unit = USECS_PER_SEC / THROTTLING_FREQUENCY;
 
-		/* Send off our tablespaces one by one */
-		foreach(lc, tablespaces)
-		{
-			tablespaceinfo *ti = (tablespaceinfo *) lfirst(lc);
-			StringInfoData buf;
+		/* Enable throttling. */
+		throttling_counter = 0;
 
-			/* Send CopyOutResponse message */
-			pq_beginmessage(&buf, 'H');
-			pq_sendbyte(&buf, 0);	/* overall format */
-			pq_sendint16(&buf, 0);	/* natts */
-			pq_endmessage(&buf);
+		/* The 'real data' starts now (header was ignored). */
+		throttled_last = GetCurrentTimestamp();
+	}
+	else
+	{
+		/* Disable throttling. */
+		throttling_counter = -1;
+	}
 
-			if (ti->path == NULL)
-			{
-				struct stat statbuf;
+	/* Send off our tablespaces one by one */
+	foreach(lc, tablespaces)
+	{
+		tablespaceinfo *ti = (tablespaceinfo *) lfirst(lc);
+		StringInfoData buf;
 
-				/* In the main tar, include the backup_label first... */
-				sendFileWithContent(BACKUP_LABEL_FILE, labelfile->data);
+		/* Send CopyOutResponse message */
+		pq_beginmessage(&buf, 'H');
+		pq_sendbyte(&buf, 0);	/* overall format */
+		pq_sendint16(&buf, 0);	/* natts */
+		pq_endmessage(&buf);
 
-				/*
-				 * Send tablespace_map file if required and then the bulk of
-				 * the files.
-				 */
-				if (tblspc_map_file && opt->sendtblspcmapfile)
-				{
-					sendFileWithContent(TABLESPACE_MAP, tblspc_map_file->data);
-					sendDir(".", 1, false, tablespaces, false);
-				}
-				else
-					sendDir(".", 1, false, tablespaces, true);
+		if (ti->path == NULL)
+		{
+			struct stat statbuf;
 
-				/* ... and pg_control after everything else. */
-				if (lstat(XLOG_CONTROL_FILE, &statbuf) != 0)
-					ereport(ERROR,
-							(errcode_for_file_access(),
-							 errmsg("could not stat file \"%s\": %m",
-									XLOG_CONTROL_FILE)));
-				sendFile(XLOG_CONTROL_FILE, XLOG_CONTROL_FILE, &statbuf, false, InvalidOid);
-			}
-			else
-				sendTablespace(ti->path, false);
+			/* In the main tar, include the backup_label first... */
+			sendFileWithContent(BACKUP_LABEL_FILE, labelfile->data);
 
 			/*
-			 * If we're including WAL, and this is the main data directory we
-			 * don't terminate the tar stream here. Instead, we will append
-			 * the xlog files below and terminate it then. This is safe since
-			 * the main data directory is always sent *last*.
+			 * Send tablespace_map file if required and then the bulk of the
+			 * files.
 			 */
-			if (opt->includewal && ti->path == NULL)
+			if (tblspc_map_file && opt->sendtblspcmapfile)
 			{
-				Assert(lnext(tablespaces, lc) == NULL);
+				sendFileWithContent(TABLESPACE_MAP, tblspc_map_file->data);
+				sendDir(".", 1, false, tablespaces, false);
 			}
 			else
-				pq_putemptymessage('c');	/* CopyDone */
+				sendDir(".", 1, false, tablespaces, true);
+
+			/* ... and pg_control after everything else. */
+			if (lstat(XLOG_CONTROL_FILE, &statbuf) != 0)
+				ereport(ERROR,
+						(errcode_for_file_access(),
+						 errmsg("could not stat file \"%s\": %m",
+								XLOG_CONTROL_FILE)));
+			sendFile(XLOG_CONTROL_FILE, XLOG_CONTROL_FILE, &statbuf, false, InvalidOid);
 		}
+		else
+			sendTablespace(ti->path, false);
 
-		endptr = do_pg_stop_backup(labelfile->data, !opt->nowait, &endtli);
+		/*
+		 * If we're including WAL, and this is the main data directory we
+		 * don't terminate the tar stream here. Instead, we will append the
+		 * xlog files below and terminate it then. This is safe since the main
+		 * data directory is always sent *last*.
+		 */
+		if (opt->includewal && ti->path == NULL)
+		{
+			Assert(lnext(tablespaces, lc) == NULL);
+		}
+		else
+			pq_putemptymessage('c');	/* CopyDone */
 	}
-	PG_END_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
 
+	endptr = do_pg_stop_backup(labelfile->data, !opt->nowait, &endtli);
 
 	if (opt->includewal)
 	{
-- 
2.21.0 (Apple Git-122.2)

