From 367a6a98bd2b8ea5c810bd081027806c6045dfd8 Mon Sep 17 00:00:00 2001
From: Mike Palmiotto <mike.palmiotto@crunchydata.com>
Date: Fri, 27 Sep 2019 19:33:15 -0400
Subject: [PATCH 4/8] Add archiver to process centralization

---
 src/backend/postmaster/pgarch.c       | 89 ++++++---------------------
 src/backend/postmaster/postmaster.c   |  4 ++
 src/include/postmaster/fork_process.h |  1 +
 src/include/postmaster/pgarch.h       |  5 +-
 4 files changed, 28 insertions(+), 71 deletions(-)

diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index f84f882c4c..53661004fd 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -92,10 +92,6 @@ static volatile sig_atomic_t ready_to_stop = false;
  * Local function forward declarations
  * ----------
  */
-#ifdef EXEC_BACKEND
-static pid_t pgarch_forkexec(void);
-#endif
-
 NON_EXEC_STATIC void PgArchiverMain(int argc, char *argv[]) pg_attribute_noreturn();
 static void pgarch_exit(SIGNAL_ARGS);
 static void ArchSigHupHandler(SIGNAL_ARGS);
@@ -115,7 +111,7 @@ static void pgarch_archiveDone(char *xlog);
  */
 
 /*
- * pgarch_start
+ * PrepPgArchiverFork
  *
  *	Called from postmaster at startup or after an existing archiver
  *	died.  Attempt to fire up a fresh archiver process.
@@ -124,17 +120,17 @@ static void pgarch_archiveDone(char *xlog);
  *
  *	Note: if fail, we will be called again from the postmaster main loop.
  */
-int
-pgarch_start(void)
+void
+PrepPgArchiverFork(ForkProcData *pgarch_fork)
 {
+	int				ac = 0;
 	time_t		curtime;
-	pid_t		pgArchPid;
 
 	/*
 	 * Do nothing if no archiver needed
 	 */
 	if (!XLogArchivingActive())
-		return 0;
+		return;
 
 	/*
 	 * Do nothing if too soon since last archiver start.  This is a safety
@@ -145,42 +141,20 @@ pgarch_start(void)
 	curtime = time(NULL);
 	if ((unsigned int) (curtime - last_pgarch_start_time) <
 		(unsigned int) PGARCH_RESTART_INTERVAL)
-		return 0;
+		return;
 	last_pgarch_start_time = curtime;
 
-#ifdef EXEC_BACKEND
-	switch ((pgArchPid = pgarch_forkexec()))
-#else
-	switch ((pgArchPid = fork_process()))
-#endif
-	{
-		case -1:
-			ereport(LOG,
-					(errmsg("could not fork archiver: %m")));
-			return 0;
-
-#ifndef EXEC_BACKEND
-		case 0:
-			/* in postmaster child ... */
-			InitPostmasterChild();
-
-			/* Close the postmaster's sockets */
-			ClosePostmasterPorts(false);
+	pgarch_fork->av[ac++] = pstrdup("postgres");
 
-			/* Drop our connection to postmaster's shared memory, as well */
-			dsm_detach_all();
-			PGSharedMemoryDetach();
-
-			PgArchiverMain(0, NULL);
-			break;
+#ifdef EXEC_BACKEND
+	pgarch_fork->av[ac++] = pstrdup("--forkarch");
+	pgarch_fork->av[ac++] = NULL;			/* filled in by postmaster_forkexec */
 #endif
+	pgarch_fork->ac = ac;
 
-		default:
-			return (int) pgArchPid;
-	}
-
-	/* shouldn't get here */
-	return 0;
+	Assert(pgarch_fork->ac < lengthof(*pgarch_fork->av));
+	pgarch_fork->child_main = PgArchiverMain;
+	pgarch_fork->type_desc = pstrdup("archiver");
 }
 
 /* ------------------------------------------------------------
@@ -189,42 +163,19 @@ pgarch_start(void)
  */
 
 
-#ifdef EXEC_BACKEND
-
-/*
- * pgarch_forkexec() -
- *
- * Format up the arglist for, then fork and exec, archive process
- */
-static pid_t
-pgarch_forkexec(void)
-{
-	char	   *av[10];
-	int			ac = 0;
-
-	av[ac++] = "postgres";
-
-	av[ac++] = "--forkarch";
-
-	av[ac++] = NULL;			/* filled in by postmaster_forkexec */
-
-	av[ac] = NULL;
-	Assert(ac < lengthof(av));
-
-	return postmaster_forkexec(ac, av);
-}
-#endif							/* EXEC_BACKEND */
-
-
 /*
  * PgArchiverMain
  *
  *	The argc/argv parameters are valid only in EXEC_BACKEND case.  However,
  *	since we don't use 'em, it hardly matters...
  */
-NON_EXEC_STATIC void
-PgArchiverMain(int argc, char *argv[])
+void
+PgArchiverMain(pg_attribute_unused() int argc, pg_attribute_unused() char *arg[])
 {
+	/* Drop our connection to postmaster's shared memory, as well */
+	dsm_detach_all();
+	PGSharedMemoryDetach();
+
 	/*
 	 * Ignore all signals usually bound to some action in the postmaster,
 	 * except for SIGHUP, SIGTERM, SIGUSR1, SIGUSR2, and SIGQUIT.
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 37a36387a3..6bdd57d1e2 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -550,6 +550,7 @@ static void ShmemBackendArrayRemove(Backend *bn);
 #define StartAutoVacLauncher()		StartChildProcess(AutoVacLauncherFork)
 #define StartAutoVacWorker()		StartChildProcess(AutoVacWorkerFork)
 #define pgstat_start()			StartChildProcess(PgstatCollectorFork)
+#define pgarch_start()			StartChildProcess(PgArchiverFork)
 
 /* Macros to check exit status of a child process */
 #define EXIT_STATUS_0(st)  ((st) == 0)
@@ -5463,6 +5464,9 @@ StartChildProcess(ForkProcType type)
 		case PgstatCollectorFork:
 			PrepPgstatCollectorFork(fork_data);
 			break;
+		case PgArchiverFork:
+			PrepPgArchiverFork(fork_data);
+			break;
 		default:
 			break;
 	}
diff --git a/src/include/postmaster/fork_process.h b/src/include/postmaster/fork_process.h
index 16ca8be968..86bad60cea 100644
--- a/src/include/postmaster/fork_process.h
+++ b/src/include/postmaster/fork_process.h
@@ -27,6 +27,7 @@ typedef enum
    AutoVacLauncherFork,
    AutoVacWorkerFork,
    PgstatCollectorFork,
+   PgArchiverFork,
 
    NUMFORKPROCTYPES			/* Must be last! */
 } ForkProcType;
diff --git a/src/include/postmaster/pgarch.h b/src/include/postmaster/pgarch.h
index 2474eac26a..ce23e39c8b 100644
--- a/src/include/postmaster/pgarch.h
+++ b/src/include/postmaster/pgarch.h
@@ -13,6 +13,8 @@
 #ifndef _PGARCH_H
 #define _PGARCH_H
 
+#include "postmaster/fork_process.h"
+
 /* ----------
  * Archiver control info.
  *
@@ -30,10 +32,9 @@
  * Functions called from postmaster
  * ----------
  */
-extern int	pgarch_start(void);
-
 #ifdef EXEC_BACKEND
 extern void PgArchiverMain(int argc, char *argv[]) pg_attribute_noreturn();
 #endif
 
+extern void PrepPgArchiverFork(ForkProcData *pgarch_fork);
 #endif							/* _PGARCH_H */
-- 
2.23.0

