From 4234a083913d93b27cd6763f41c092adc8d4cf6c Mon Sep 17 00:00:00 2001
From: Mike Palmiotto <mike.palmiotto@crunchydata.com>
Date: Mon, 9 Mar 2020 22:12:10 +0000
Subject: [PATCH v2 01/12] Add subprocess infrastructure

This commit introduces a new infrastructure for postmaster subprocesses
initialization, forking, exec'ing and main function control. The intent
is to have all subprocess control information live in the process_types
struct, defined in subprocess.h. As more processes are added to the
struct, the fields will be expanded to differentiate actions.

There are several advantages to such an infrastructure:
1) Centralized definition of subprocess information
2) Standardized function arguments/naming schemes
3) Code minimization and removal of duplicate code
---
 src/backend/bootstrap/bootstrap.c     | 74 +++++++--------------------
 src/backend/postmaster/Makefile       |  1 +
 src/backend/postmaster/bgwriter.c     |  2 +-
 src/backend/postmaster/checkpointer.c |  2 +-
 src/backend/postmaster/startup.c      |  3 +-
 src/backend/postmaster/subprocess.c   | 62 ++++++++++++++++++++++
 src/backend/postmaster/walwriter.c    |  2 +-
 src/backend/replication/walreceiver.c |  2 +-
 src/include/bootstrap/bootstrap.h     |  3 +-
 src/include/postmaster/bgwriter.h     |  4 +-
 src/include/postmaster/startup.h      |  5 +-
 src/include/postmaster/subprocess.h   | 44 ++++++++++++++++
 src/include/postmaster/walwriter.h    |  2 +-
 src/include/replication/walreceiver.h |  2 +-
 14 files changed, 140 insertions(+), 68 deletions(-)
 create mode 100644 src/backend/postmaster/subprocess.c
 create mode 100644 src/include/postmaster/subprocess.h

diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 5480a024e0..9d41567467 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -35,6 +35,7 @@
 #include "pgstat.h"
 #include "postmaster/bgwriter.h"
 #include "postmaster/startup.h"
+#include "postmaster/subprocess.h"
 #include "postmaster/walwriter.h"
 #include "replication/walreceiver.h"
 #include "storage/bufmgr.h"
@@ -56,8 +57,6 @@ uint32		bootstrap_data_checksum_version = 0;	/* No checksum */
 #define ALLOC(t, c) \
 	((t *) MemoryContextAllocZero(TopMemoryContext, (unsigned)(c) * sizeof(t)))
 
-static void CheckerModeMain(void);
-static void BootstrapModeMain(void);
 static void bootstrap_signals(void);
 static void ShutdownAuxiliaryProcess(int code, Datum arg);
 static Form_pg_attribute AllocateAttribute(void);
@@ -334,6 +333,12 @@ AuxiliaryProcessMain(int argc, char *argv[])
 		default:
 			MyBackendType = B_INVALID;
 	}
+
+	/*
+	 * We've read the arguments and know what backend type we are.
+	 */
+	InitMySubprocess((SubprocessType)MyAuxProcType);
+
 	if (IsUnderPostmaster)
 		init_ps_display(NULL);
 
@@ -418,56 +423,10 @@ AuxiliaryProcessMain(int argc, char *argv[])
 	 */
 	SetProcessingMode(NormalProcessing);
 
-	switch (MyAuxProcType)
-	{
-		case CheckerProcess:
-			/* don't set signals, they're useless here */
-			CheckerModeMain();
-			proc_exit(1);		/* should never return */
-
-		case BootstrapProcess:
-
-			/*
-			 * There was a brief instant during which mode was Normal; this is
-			 * okay.  We need to be in bootstrap mode during BootStrapXLOG for
-			 * the sake of multixact initialization.
-			 */
-			SetProcessingMode(BootstrapProcessing);
-			bootstrap_signals();
-			BootStrapXLOG();
-			BootstrapModeMain();
-			proc_exit(1);		/* should never return */
-
-		case StartupProcess:
-			/* don't set signals, startup process has its own agenda */
-			StartupProcessMain();
-			proc_exit(1);		/* should never return */
-
-		case BgWriterProcess:
-			/* don't set signals, bgwriter has its own agenda */
-			BackgroundWriterMain();
-			proc_exit(1);		/* should never return */
-
-		case CheckpointerProcess:
-			/* don't set signals, checkpointer has its own agenda */
-			CheckpointerMain();
-			proc_exit(1);		/* should never return */
-
-		case WalWriterProcess:
-			/* don't set signals, walwriter has its own agenda */
-			InitXLOGAccess();
-			WalWriterMain();
-			proc_exit(1);		/* should never return */
-
-		case WalReceiverProcess:
-			/* don't set signals, walreceiver has its own agenda */
-			WalReceiverMain();
-			proc_exit(1);		/* should never return */
+	/* Now jump into the subprocess main function and never look back! */
+	MySubprocess->entrypoint(argc, argv);
 
-		default:
-			elog(PANIC, "unrecognized process type: %d", (int) MyAuxProcType);
-			proc_exit(1);
-	}
+	proc_exit(1);		/* should never return */
 }
 
 /*
@@ -476,8 +435,8 @@ AuxiliaryProcessMain(int argc, char *argv[])
  * settings).  Since, in fact, that was already done by BaseInit(),
  * we have nothing more to do here.
  */
-static void
-CheckerModeMain(void)
+void
+CheckerModeMain(int argc, char *argv[])
 {
 	proc_exit(0);
 }
@@ -489,11 +448,15 @@ CheckerModeMain(void)
  *	 The bootstrap backend doesn't speak SQL, but instead expects
  *	 commands in a special bootstrap language.
  */
-static void
-BootstrapModeMain(void)
+void
+BootstrapModeMain(int argc, char *argv[])
 {
 	int			i;
 
+	SetProcessingMode(BootstrapProcessing);
+	bootstrap_signals();
+	BootStrapXLOG();
+
 	Assert(!IsUnderPostmaster);
 	Assert(IsBootstrapProcessingMode());
 
@@ -508,7 +471,6 @@ BootstrapModeMain(void)
 	 * Do backend-like initialization for bootstrap mode
 	 */
 	InitProcess();
-
 	InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL, false);
 
 	/* Initialize stuff for bootstrap-file processing */
diff --git a/src/backend/postmaster/Makefile b/src/backend/postmaster/Makefile
index bfdf6a833d..52b4c2142c 100644
--- a/src/backend/postmaster/Makefile
+++ b/src/backend/postmaster/Makefile
@@ -23,6 +23,7 @@ OBJS = \
 	pgstat.o \
 	postmaster.o \
 	startup.o \
+	subprocess.o \
 	syslogger.o \
 	walwriter.o
 
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index 069e27e427..b2170938f3 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -91,7 +91,7 @@ static XLogRecPtr last_snapshot_lsn = InvalidXLogRecPtr;
  * basic execution environment, but not enabled signals yet.
  */
 void
-BackgroundWriterMain(void)
+BackgroundWriterMain(int argc, char *argv[])
 {
 	sigjmp_buf	local_sigjmp_buf;
 	MemoryContext bgwriter_context;
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index e354a78725..83f7be1b1e 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -180,7 +180,7 @@ static void ReqCheckpointHandler(SIGNAL_ARGS);
  * basic execution environment, but not enabled signals yet.
  */
 void
-CheckpointerMain(void)
+CheckpointerMain(int argc, char *argv[])
 {
 	sigjmp_buf	local_sigjmp_buf;
 	MemoryContext checkpointer_context;
diff --git a/src/backend/postmaster/startup.c b/src/backend/postmaster/startup.c
index c2250d7d4e..e29649a6a1 100644
--- a/src/backend/postmaster/startup.c
+++ b/src/backend/postmaster/startup.c
@@ -127,13 +127,12 @@ HandleStartupProcInterrupts(void)
 		ProcessProcSignalBarrier();
 }
 
-
 /* ----------------------------------
  *	Startup Process main entry point
  * ----------------------------------
  */
 void
-StartupProcessMain(void)
+StartupProcessMain(int argc, char *argv[])
 {
 	/*
 	 * Properly accept or ignore signals the postmaster might send us.
diff --git a/src/backend/postmaster/subprocess.c b/src/backend/postmaster/subprocess.c
new file mode 100644
index 0000000000..3e7a45bf10
--- /dev/null
+++ b/src/backend/postmaster/subprocess.c
@@ -0,0 +1,62 @@
+/*-------------------------------------------------------------------------
+ *
+ * subprocess.c
+ *
+ * Copyright (c) 2004-2020, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ *	  src/backend/postmaster/syslogger.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+#include "bootstrap/bootstrap.h"
+#include "postmaster/bgwriter.h"
+#include "postmaster/postmaster.h"
+#include "postmaster/startup.h"
+#include "postmaster/subprocess.h"
+#include "postmaster/walwriter.h"
+#include "replication/walreceiver.h"
+
+SubprocessType		MySubprocessType;
+PgSubprocess	   *MySubprocess;
+
+static PgSubprocess process_types[] = {
+	{
+		.desc = "checker",
+		.entrypoint = CheckerModeMain
+	},
+	{
+		.desc = "bootstrap",
+		.entrypoint = BootstrapModeMain
+	},
+	{
+		.desc = "startup",
+		.entrypoint = StartupProcessMain
+	},
+	{
+		.desc = "background writer",
+		.entrypoint = BackgroundWriterMain
+	},
+	{
+		.desc = "checkpointer",
+		.entrypoint = CheckpointerMain
+	},
+	{
+		.desc = "wal writer",
+		.entrypoint = WalWriterMain
+	},
+	{
+		.desc = "wal receiver",
+		.entrypoint = WalReceiverMain
+	}
+};
+
+void
+InitMySubprocess(SubprocessType type)
+{
+	MySubprocessType = type;
+	MySubprocess = &process_types[type];
+	MySubprocess->desc = gettext(MySubprocess->desc);
+}
diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c
index 45a2757969..3a0cec3371 100644
--- a/src/backend/postmaster/walwriter.c
+++ b/src/backend/postmaster/walwriter.c
@@ -85,7 +85,7 @@ int			WalWriterFlushAfter = 128;
  * basic execution environment, but not enabled signals yet.
  */
 void
-WalWriterMain(void)
+WalWriterMain(int argc, char *argv[])
 {
 	sigjmp_buf	local_sigjmp_buf;
 	MemoryContext walwriter_context;
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 25e0333c9e..cd39a8c982 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -165,7 +165,7 @@ ProcessWalRcvInterrupts(void)
 
 /* Main entry point for walreceiver process */
 void
-WalReceiverMain(void)
+WalReceiverMain(int argc, char *argv[])
 {
 	char		conninfo[MAXCONNINFO];
 	char	   *tmp_conninfo;
diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h
index b67fa9acc1..f85cfb5202 100644
--- a/src/include/bootstrap/bootstrap.h
+++ b/src/include/bootstrap/bootstrap.h
@@ -16,7 +16,6 @@
 
 #include "nodes/execnodes.h"
 
-
 /*
  * MAXATTR is the maximum number of attributes in a relation supported
  * at bootstrap time (i.e., the max possible in a system table).
@@ -31,6 +30,8 @@ extern Relation boot_reldesc;
 extern Form_pg_attribute attrtypes[MAXATTR];
 extern int	numattr;
 
+extern void CheckerModeMain(int argc, char *argv[]);
+extern void BootstrapModeMain(int argc, char *argv[]);
 
 extern void AuxiliaryProcessMain(int argc, char *argv[]) pg_attribute_noreturn();
 
diff --git a/src/include/postmaster/bgwriter.h b/src/include/postmaster/bgwriter.h
index 0a5708b32e..6fb1ee1d6d 100644
--- a/src/include/postmaster/bgwriter.h
+++ b/src/include/postmaster/bgwriter.h
@@ -27,8 +27,8 @@ extern int	CheckPointTimeout;
 extern int	CheckPointWarning;
 extern double CheckPointCompletionTarget;
 
-extern void BackgroundWriterMain(void) pg_attribute_noreturn();
-extern void CheckpointerMain(void) pg_attribute_noreturn();
+extern void BackgroundWriterMain(int argc, char *argv[]) pg_attribute_noreturn();
+extern void CheckpointerMain(int argc, char *argv[]) pg_attribute_noreturn();
 
 extern void RequestCheckpoint(int flags);
 extern void CheckpointWriteDelay(int flags, double progress);
diff --git a/src/include/postmaster/startup.h b/src/include/postmaster/startup.h
index 9f59c1ffa3..6a8108dfe0 100644
--- a/src/include/postmaster/startup.h
+++ b/src/include/postmaster/startup.h
@@ -13,10 +13,13 @@
 #define _STARTUP_H
 
 extern void HandleStartupProcInterrupts(void);
-extern void StartupProcessMain(void) pg_attribute_noreturn();
 extern void PreRestoreCommand(void);
 extern void PostRestoreCommand(void);
 extern bool IsPromoteTriggered(void);
 extern void ResetPromoteTriggered(void);
 
+/* Startup subprocess functions */
+extern void StartupProcessMain(int argc, char *argv[]) pg_attribute_noreturn();
+extern bool StartupCleanup(int child_errno);
+
 #endif							/* _STARTUP_H */
diff --git a/src/include/postmaster/subprocess.h b/src/include/postmaster/subprocess.h
new file mode 100644
index 0000000000..56e8edf2d8
--- /dev/null
+++ b/src/include/postmaster/subprocess.h
@@ -0,0 +1,44 @@
+/*-------------------------------------------------------------------------
+ *
+ * subprocess.h
+ *
+ * Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ * src/include/postmaster/subprocess.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SUBPROCESS_H
+#define SUBPROCESS_H
+
+#include "postmaster.h"
+
+typedef enum
+{
+	NoProcessType = -1,
+	CheckerType = 0,
+	BootstrapType,
+	StartupType,
+	BgWriterType,
+	CheckpointerType,
+	WalWriterType,
+	WalReceiverType,	/* end of Auxiliary Process Forks */
+
+	NUMSUBPROCESSTYPES			/* Must be last! */
+} SubprocessType;
+
+typedef void (*SubprocessEntryPoint) (int argc, char *argv[]);
+
+/* Current subprocess initializer */
+extern void InitMySubprocess(SubprocessType type);
+
+typedef struct PgSubprocess
+{
+	const char			   *desc;
+	SubprocessEntryPoint	entrypoint;
+} PgSubprocess;
+
+extern SubprocessType				MySubprocessType;
+extern PGDLLIMPORT PgSubprocess	   *MySubprocess;
+
+#endif							/* SUBPROCESS_H */
diff --git a/src/include/postmaster/walwriter.h b/src/include/postmaster/walwriter.h
index 011dc26a6e..596c437c54 100644
--- a/src/include/postmaster/walwriter.h
+++ b/src/include/postmaster/walwriter.h
@@ -16,6 +16,6 @@
 extern int	WalWriterDelay;
 extern int	WalWriterFlushAfter;
 
-extern void WalWriterMain(void) pg_attribute_noreturn();
+extern void WalWriterMain(int argc, char *argv[]) pg_attribute_noreturn();
 
 #endif							/* _WALWRITER_H */
diff --git a/src/include/replication/walreceiver.h b/src/include/replication/walreceiver.h
index e08afc6548..2025f19ab3 100644
--- a/src/include/replication/walreceiver.h
+++ b/src/include/replication/walreceiver.h
@@ -311,7 +311,7 @@ walrcv_clear_result(WalRcvExecResult *walres)
 }
 
 /* prototypes for functions in walreceiver.c */
-extern void WalReceiverMain(void) pg_attribute_noreturn();
+extern void WalReceiverMain(int argc, char *argv[]);
 extern void ProcessWalRcvInterrupts(void);
 
 /* prototypes for functions in walreceiverfuncs.c */
-- 
2.17.0

