From be1b8bd29985572598fd5881ec6e0854f9138dac Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Tue, 26 Nov 2019 13:14:13 -0500
Subject: [PATCH v3 1/5] Move interrupting-handling code into subroutines.

Some auxiliary processes, as well as the autovacuum launcher,
have interrupt handling code directly in their main loops.
Try to abstract things a little better by moving it into
separate functions.

This doesn't make any functional difference, and leaves
in place relatively large differences among processes in how
interrupts are handled, but hopefully it at least makes it
easier to see the commonalities and differences across
process types.
---
 src/backend/postmaster/autovacuum.c   | 72 +++++++++++++++++----------
 src/backend/postmaster/bgwriter.c     | 42 ++++++++++------
 src/backend/postmaster/checkpointer.c | 71 ++++++++++++++------------
 src/backend/postmaster/walwriter.c    | 34 ++++++++-----
 4 files changed, 133 insertions(+), 86 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c1dd8168ca..5766203aaf 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -311,6 +311,8 @@ NON_EXEC_STATIC void AutoVacWorkerMain(int argc, char *argv[]) pg_attribute_nore
 NON_EXEC_STATIC void AutoVacLauncherMain(int argc, char *argv[]) pg_attribute_noreturn();
 
 static Oid	do_start_worker(void);
+static void HandleAutoVacLauncherInterrupts(void);
+static void AutoVacLauncherShutdown() pg_attribute_noreturn();
 static void launcher_determine_sleep(bool canlaunch, bool recursing,
 									 struct timeval *nap);
 static void launch_worker(TimestampTz now);
@@ -554,7 +556,7 @@ AutoVacLauncherMain(int argc, char *argv[])
 
 		/* if in shutdown mode, no need for anything further; just go away */
 		if (got_SIGTERM)
-			goto shutdown;
+			AutoVacLauncherShutdown();
 
 		/*
 		 * Sleep at least 1 second after any error.  We don't want to be
@@ -649,30 +651,7 @@ AutoVacLauncherMain(int argc, char *argv[])
 
 		ResetLatch(MyLatch);
 
-		/* Process sinval catchup interrupts that happened while sleeping */
-		ProcessCatchupInterrupt();
-
-		/* the normal shutdown case */
-		if (got_SIGTERM)
-			break;
-
-		if (got_SIGHUP)
-		{
-			got_SIGHUP = false;
-			ProcessConfigFile(PGC_SIGHUP);
-
-			/* shutdown requested in config file? */
-			if (!AutoVacuumingActive())
-				break;
-
-			/* rebalance in case the default cost parameters changed */
-			LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
-			autovac_balance_cost();
-			LWLockRelease(AutovacuumLock);
-
-			/* rebuild the list in case the naptime changed */
-			rebuild_database_list(InvalidOid);
-		}
+		HandleAutoVacLauncherInterrupts();
 
 		/*
 		 * a worker finished, or postmaster signalled failure to start a
@@ -813,8 +792,47 @@ AutoVacLauncherMain(int argc, char *argv[])
 		}
 	}
 
-	/* Normal exit from the autovac launcher is here */
-shutdown:
+	AutoVacLauncherShutdown();
+}
+
+/*
+ * Process any new interrupts.
+ */
+static void
+HandleAutoVacLauncherInterrupts(void)
+{
+	/* the normal shutdown case */
+	if (got_SIGTERM)
+		AutoVacLauncherShutdown();
+
+	if (got_SIGHUP)
+	{
+		got_SIGHUP = false;
+		ProcessConfigFile(PGC_SIGHUP);
+
+		/* shutdown requested in config file? */
+		if (!AutoVacuumingActive())
+			AutoVacLauncherShutdown();
+
+		/* rebalance in case the default cost parameters changed */
+		LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
+		autovac_balance_cost();
+		LWLockRelease(AutovacuumLock);
+
+		/* rebuild the list in case the naptime changed */
+		rebuild_database_list(InvalidOid);
+	}
+
+	/* Process sinval catchup interrupts that happened while sleeping */
+	ProcessCatchupInterrupt();
+}
+
+/*
+ * Perform a normal exit from the autovac launcher.
+ */
+static void
+AutoVacLauncherShutdown()
+{
 	ereport(DEBUG1,
 			(errmsg("autovacuum launcher shutting down")));
 	AutoVacuumShmem->av_launcherpid = 0;
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index 2fa631ea7a..c7500f1d71 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -92,6 +92,8 @@ static XLogRecPtr last_snapshot_lsn = InvalidXLogRecPtr;
 static volatile sig_atomic_t got_SIGHUP = false;
 static volatile sig_atomic_t shutdown_requested = false;
 
+static void HandleBackgroundWriterInterrupts(void);
+
 /* Signal handlers */
 
 static void bg_quickdie(SIGNAL_ARGS);
@@ -241,21 +243,7 @@ BackgroundWriterMain(void)
 		/* Clear any already-pending wakeups */
 		ResetLatch(MyLatch);
 
-		if (got_SIGHUP)
-		{
-			got_SIGHUP = false;
-			ProcessConfigFile(PGC_SIGHUP);
-		}
-		if (shutdown_requested)
-		{
-			/*
-			 * From here on, elog(ERROR) should end with exit(1), not send
-			 * control back to the sigsetjmp block above
-			 */
-			ExitOnAnyError = true;
-			/* Normal exit from the bgwriter is here */
-			proc_exit(0);		/* done */
-		}
+		HandleBackgroundWriterInterrupts();
 
 		/*
 		 * Do one cycle of dirty-buffer writing.
@@ -369,6 +357,30 @@ BackgroundWriterMain(void)
 	}
 }
 
+/*
+ * Process any new interrupts.
+ */
+static void
+HandleBackgroundWriterInterrupts(void)
+{
+	if (got_SIGHUP)
+	{
+		got_SIGHUP = false;
+		ProcessConfigFile(PGC_SIGHUP);
+	}
+
+	if (shutdown_requested)
+	{
+		/*
+		 * From here on, elog(ERROR) should end with exit(1), not send
+		 * control back to the sigsetjmp block above
+		 */
+		ExitOnAnyError = true;
+		/* Normal exit from the bgwriter is here */
+		proc_exit(0);		/* done */
+	}
+}
+
 
 /* --------------------------------
  *		signal handler routines
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index d93c941871..d087ee9c74 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -169,6 +169,7 @@ static pg_time_t last_xlog_switch_time;
 
 /* Prototypes for private functions */
 
+static void HandleCheckpointerInterrupts();
 static void CheckArchiveTimeout(void);
 static bool IsCheckpointOnSchedule(double progress);
 static bool ImmediateCheckpointRequested(void);
@@ -350,37 +351,7 @@ CheckpointerMain(void)
 		 * Process any requests or signals received recently.
 		 */
 		AbsorbSyncRequests();
-
-		if (got_SIGHUP)
-		{
-			got_SIGHUP = false;
-			ProcessConfigFile(PGC_SIGHUP);
-
-			/*
-			 * Checkpointer is the last process to shut down, so we ask it to
-			 * hold the keys for a range of other tasks required most of which
-			 * have nothing to do with checkpointing at all.
-			 *
-			 * For various reasons, some config values can change dynamically
-			 * so the primary copy of them is held in shared memory to make
-			 * sure all backends see the same value.  We make Checkpointer
-			 * responsible for updating the shared memory copy if the
-			 * parameter setting changes because of SIGHUP.
-			 */
-			UpdateSharedMemoryConfig();
-		}
-		if (shutdown_requested)
-		{
-			/*
-			 * From here on, elog(ERROR) should end with exit(1), not send
-			 * control back to the sigsetjmp block above
-			 */
-			ExitOnAnyError = true;
-			/* Close down the database */
-			ShutdownXLOG(0, 0);
-			/* Normal exit from the checkpointer is here */
-			proc_exit(0);		/* done */
-		}
+		HandleCheckpointerInterrupts();
 
 		/*
 		 * Detect a pending checkpoint request by checking whether the flags
@@ -558,6 +529,44 @@ CheckpointerMain(void)
 	}
 }
 
+/*
+ * Process any new interrupts.
+ */
+static void
+HandleCheckpointerInterrupts(void)
+{
+	if (got_SIGHUP)
+	{
+		got_SIGHUP = false;
+		ProcessConfigFile(PGC_SIGHUP);
+
+		/*
+		 * Checkpointer is the last process to shut down, so we ask it to
+		 * hold the keys for a range of other tasks required most of which
+		 * have nothing to do with checkpointing at all.
+		 *
+		 * For various reasons, some config values can change dynamically
+		 * so the primary copy of them is held in shared memory to make
+		 * sure all backends see the same value.  We make Checkpointer
+		 * responsible for updating the shared memory copy if the
+		 * parameter setting changes because of SIGHUP.
+		 */
+		UpdateSharedMemoryConfig();
+	}
+	if (shutdown_requested)
+	{
+		/*
+		 * From here on, elog(ERROR) should end with exit(1), not send
+		 * control back to the sigsetjmp block above
+		 */
+		ExitOnAnyError = true;
+		/* Close down the database */
+		ShutdownXLOG(0, 0);
+		/* Normal exit from the checkpointer is here */
+		proc_exit(0);		/* done */
+	}
+}
+
 /*
  * CheckArchiveTimeout -- check for archive_timeout and switch xlog files
  *
diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c
index cce9713408..5a3573503c 100644
--- a/src/backend/postmaster/walwriter.c
+++ b/src/backend/postmaster/walwriter.c
@@ -83,6 +83,8 @@ int			WalWriterFlushAfter = 128;
 static volatile sig_atomic_t got_SIGHUP = false;
 static volatile sig_atomic_t shutdown_requested = false;
 
+static void HandleWalWriterInterrupts(void);
+
 /* Signal handlers */
 static void wal_quickdie(SIGNAL_ARGS);
 static void WalSigHupHandler(SIGNAL_ARGS);
@@ -242,19 +244,7 @@ WalWriterMain(void)
 		/* Clear any already-pending wakeups */
 		ResetLatch(MyLatch);
 
-		/*
-		 * Process any requests or signals received recently.
-		 */
-		if (got_SIGHUP)
-		{
-			got_SIGHUP = false;
-			ProcessConfigFile(PGC_SIGHUP);
-		}
-		if (shutdown_requested)
-		{
-			/* Normal exit from the walwriter is here */
-			proc_exit(0);		/* done */
-		}
+		HandleWalWriterInterrupts();
 
 		/*
 		 * Do what we're here for; then, if XLogBackgroundFlush() found useful
@@ -282,6 +272,24 @@ WalWriterMain(void)
 	}
 }
 
+/*
+ * Process any new interrupts.
+ */
+static void
+HandleWalWriterInterrupts(void)
+{
+	if (got_SIGHUP)
+	{
+		got_SIGHUP = false;
+		ProcessConfigFile(PGC_SIGHUP);
+	}
+	if (shutdown_requested)
+	{
+		/* Normal exit from the walwriter is here */
+		proc_exit(0);		/* done */
+	}
+}
+
 
 /* --------------------------------
  *		signal handler routines
-- 
2.17.2 (Apple Git-113)

