From aeddc2a60d7fcfdb06b20162478212fa87732db9 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Thu, 25 Dec 2003 03:52:51 +0000
Subject: [PATCH] Continued rearrangement to permit pgstat + BootstrapMain
 processes to be fork/exec'd, in the same mode as the previous patch for
 backends.

Claudio Natoli
---
 src/backend/bootstrap/bootstrap.c   |  42 +++---
 src/backend/main/main.c             |  31 ++++-
 src/backend/postmaster/pgstat.c     | 204 ++++++++++++++++++++++------
 src/backend/postmaster/postmaster.c | 157 ++++++++++++---------
 src/backend/storage/lmgr/proc.c     |  39 +++---
 src/backend/tcop/postgres.c         |   6 +-
 src/include/pgstat.h                |  25 +++-
 7 files changed, 345 insertions(+), 159 deletions(-)

diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 4820582eb3f..f42c071195f 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.171 2003/12/20 17:31:21 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.172 2003/12/25 03:52:50 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -48,6 +48,11 @@
 
 #define ALLOC(t, c)		((t *) calloc((unsigned)(c), sizeof(t)))
 
+#ifdef EXEC_BACKEND
+typedef struct Port Port;
+extern void SSDataBaseInit(int);
+extern void read_backend_variables(pid_t, Port*);
+#endif
 
 extern int	Int_yyparse(void);
 static hashnode *AddStr(char *str, int strlength, int mderef);
@@ -238,7 +243,7 @@ BootstrapMain(int argc, char *argv[])
 	 *
 	 * If we are running under the postmaster, this is done already.
 	 */
-	if (!IsUnderPostmaster /* when exec || ExecBackend */ )
+	if (!IsUnderPostmaster || ExecBackend)
 		MemoryContextInit();
 
 	/*
@@ -247,7 +252,7 @@ BootstrapMain(int argc, char *argv[])
 
 	/* Set defaults, to be overriden by explicit options below */
 	dbname = NULL;
-	if (!IsUnderPostmaster /* when exec || ExecBackend */ )
+	if (!IsUnderPostmaster)
 	{
 		InitializeGUCOptions();
 		potential_DataDir = getenv("PGDATA");	/* Null if no PGDATA
@@ -285,24 +290,11 @@ BootstrapMain(int argc, char *argv[])
 				xlogop = atoi(optarg);
 				break;
 			case 'p':
-				{
-					/* indicates fork from postmaster */
 #ifdef EXEC_BACKEND
-					char	   *p;
-
-					sscanf(optarg, "%lu,%p,",
-						   &UsedShmemSegID,
-						   &UsedShmemSegAddr);
-					p = strchr(optarg, ',');
-					if (p)
-						p = strchr(p + 1, ',');
-					if (p)
-						dbname = strdup(p + 1);
-#else
-					dbname = strdup(optarg);
+				IsUnderPostmaster = true;
 #endif
+				dbname = strdup(optarg);
 					break;
-				}
 			case 'B':
 				SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV);
 				break;
@@ -347,12 +339,7 @@ BootstrapMain(int argc, char *argv[])
 	if (!dbname || argc != optind)
 		usage();
 
-#ifdef EXEC_BACKEND
-	if (IsUnderPostmaster && MyProc /* ordinary backend */ )
-		AttachSharedMemoryAndSemaphores();
-#endif
-
-	if (!IsUnderPostmaster /* when exec || ExecBackend */ )
+	if (!IsUnderPostmaster || ExecBackend)
 	{
 		if (!potential_DataDir)
 		{
@@ -376,6 +363,9 @@ BootstrapMain(int argc, char *argv[])
 	{
 #ifdef EXEC_BACKEND
 		read_nondefault_variables();
+		read_backend_variables(getpid(),NULL);
+
+		SSDataBaseInit(xlogop);
 #endif
 	}
 	else
@@ -427,6 +417,10 @@ BootstrapMain(int argc, char *argv[])
 	SetProcessingMode(BootstrapProcessing);
 	IgnoreSystemIndexes(true);
 
+#ifdef EXEC_BACKEND
+	if (IsUnderPostmaster)
+		AttachSharedMemoryAndSemaphores();
+#endif
 	XLOGPathInit();
 
 	BaseInit();
diff --git a/src/backend/main/main.c b/src/backend/main/main.c
index 854b1635776..84036314cd1 100644
--- a/src/backend/main/main.c
+++ b/src/backend/main/main.c
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/main/main.c,v 1.68 2003/12/23 00:34:04 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/main/main.c,v 1.69 2003/12/25 03:52:50 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -39,6 +39,7 @@
 #include "tcop/tcopprot.h"
 #include "utils/help_config.h"
 #include "utils/ps_status.h"
+#include "pgstat.h"
 
 
 
@@ -202,9 +203,9 @@ main(int argc, char *argv[])
 
 	/*
 	 * Now dispatch to one of PostmasterMain, PostgresMain, GucInfoMain,
-	 * or BootstrapMain depending on the program name (and possibly first
-	 * argument) we were called with.  The lack of consistency here is
-	 * historical.
+	 * pgstat_main, pgstat_mainChild or BootstrapMain depending on the
+	 * program name (and possibly first argument) we were called with.
+	 * The lack of consistency here is historical.
 	 */
 	len = strlen(new_argv[0]);
 
@@ -221,6 +222,28 @@ main(int argc, char *argv[])
 	if (argc > 1 && strcmp(new_argv[1], "-boot") == 0)
 		exit(BootstrapMain(argc - 1, new_argv + 1));
 
+#ifdef EXEC_BACKEND
+	/*
+	 * If the first argument is "-statBuf", then invoke pgstat_main. Note
+	 * we remove "-statBuf" from the arguments passed on to pgstat_main.
+	 */
+	if (argc > 1 && strcmp(new_argv[1], "-statBuf") == 0)
+	{
+		pgstat_main(argc - 2, new_argv + 2);
+		exit(0);
+	}
+
+	/*
+	 * If the first argument is "-statCol", then invoke pgstat_mainChild. Note
+	 * we remove "-statCol" from the arguments passed on to pgstat_mainChild.
+	 */
+	if (argc > 1 && strcmp(new_argv[1], "-statCol") == 0)
+	{
+		pgstat_mainChild(argc - 2, new_argv + 2);
+		exit(0);
+	}
+#endif
+
 	/*
 	 * If the first argument is "--describe-config", then invoke runtime
 	 * configuration option display mode.
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 38323f45ba2..90689d2f4e6 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -13,7 +13,7 @@
  *
  *	Copyright (c) 2001-2003, PostgreSQL Global Development Group
  *
- *	$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.49 2003/12/20 17:31:21 momjian Exp $
+ *	$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.50 2003/12/25 03:52:51 momjian Exp $
  * ----------
  */
 #include "postgres.h"
@@ -106,7 +106,13 @@ static char pgStat_fname[MAXPGPATH];
  * Local function forward declarations
  * ----------
  */
-static void pgstat_main(void);
+#ifdef EXEC_BACKEND
+static void pgstat_exec(STATS_PROCESS_TYPE procType);
+static void pgstat_parseArgs(PGSTAT_FORK_ARGS);
+#endif
+NON_EXEC_STATIC void pgstat_main(PGSTAT_FORK_ARGS);
+NON_EXEC_STATIC void pgstat_mainChild(PGSTAT_FORK_ARGS);
+static void pgstat_mainInit(void);
 static void pgstat_recvbuffer(void);
 static void pgstat_die(SIGNAL_ARGS);
 
@@ -328,6 +334,89 @@ startup_failed:
 }
 
 
+#ifdef EXEC_BACKEND
+
+/* ----------
+ * pgstat_exec() -
+ *
+ * Used to format up the arglist for, and exec, statistics
+ * (buffer and collector) processes
+ *
+ */
+static void
+pgstat_exec(STATS_PROCESS_TYPE procType)
+{
+	char *av[11];
+	int ac = 0, bufc = 0, i;
+	char pgstatBuf[8][MAXPGPATH];
+
+	av[ac++] = "postgres";
+	switch (procType)
+	{
+		case STAT_PROC_BUFFER:
+			av[ac++] = "-statBuf";
+			break;
+
+		case STAT_PROC_COLLECTOR:
+			av[ac++] = "-statCol";
+			break;
+
+		default:
+			Assert(false);
+	}
+
+	/* Sockets + pipes */
+	bufc = 0;
+	snprintf(pgstatBuf[bufc++],MAXPGPATH,"%d",pgStatSock);
+	snprintf(pgstatBuf[bufc++],MAXPGPATH,"%d",pgStatPmPipe[0]);
+	snprintf(pgstatBuf[bufc++],MAXPGPATH,"%d",pgStatPmPipe[1]);
+	snprintf(pgstatBuf[bufc++],MAXPGPATH,"%d",pgStatPipe[0]);
+	snprintf(pgstatBuf[bufc++],MAXPGPATH,"%d",pgStatPipe[1]);
+
+	/* + the pstat file names, and postgres pathname */
+	/* FIXME: [fork/exec] whitespaces in directories? */
+	snprintf(pgstatBuf[bufc++],MAXPGPATH,"%s",pgStat_tmpfname);
+	snprintf(pgstatBuf[bufc++],MAXPGPATH,"%s",pgStat_fname);
+	snprintf(pgstatBuf[bufc++],MAXPGPATH,"%s",pg_pathname);
+
+	/* Add to the arg list */
+	Assert(bufc <= lengthof(pgstatBuf));
+	for (i = 0; i < bufc; i++)
+		av[ac++] = pgstatBuf[i];
+
+	av[ac++] = NULL;
+	Assert(ac <= lengthof(av));
+
+	if (execv(pg_pathname,av) == -1)
+		/* FIXME: [fork/exec] suggestions for what to do here? Can't call elog... */
+		Assert(false);
+}
+
+
+/* ----------
+ * pgstat_parseArgs() -
+ *
+ * Used to unformat the arglist for exec'ed statistics
+ * (buffer and collector) processes
+ *
+ */
+static void
+pgstat_parseArgs(PGSTAT_FORK_ARGS)
+{
+	Assert(argc == 8);
+	argc = 0;
+	pgStatSock 		= atoi(argv[argc++]);
+	pgStatPmPipe[0]	= atoi(argv[argc++]);
+	pgStatPmPipe[1]	= atoi(argv[argc++]);
+	pgStatPipe[0]	= atoi(argv[argc++]);
+	pgStatPipe[1]	= atoi(argv[argc++]);
+	strncpy(pgStat_tmpfname,argv[argc++],MAXPGPATH);
+	strncpy(pgStat_fname,	argv[argc++],MAXPGPATH);
+	strncpy(pg_pathname,	argv[argc++],MAXPGPATH);
+}
+
+#endif
+
 /* ----------
  * pgstat_start() -
  *
@@ -416,22 +505,17 @@ pgstat_start(void)
 	beos_backend_startup();
 #endif
 
-	IsUnderPostmaster = true;	/* we are a postmaster subprocess now */
-
-	MyProcPid = getpid();		/* reset MyProcPid */
-
-	/* Lose the postmaster's on-exit routines */
-	on_exit_reset();
-
 	/* Close the postmaster's sockets, except for pgstat link */
 	ClosePostmasterPorts(false);
 
 	/* Drop our connection to postmaster's shared memory, as well */
 	PGSharedMemoryDetach();
 
+#ifdef EXEC_BACKEND
+	pgstat_exec(STAT_PROC_BUFFER);
+#else
 	pgstat_main();
-
-	exit(0);
+#endif
 }
 
 
@@ -1228,35 +1312,15 @@ pgstat_send(void *msg, int len)
  *------------------------------------------------------------
  */
 
-
-/* ----------
- * pgstat_main() -
- *
- *	Start up the statistics collector itself.  This is the body of the
- *	postmaster child process.
- * ----------
- */
 static void
-pgstat_main(void)
+pgstat_mainInit(void)
 {
-	PgStat_Msg	msg;
-	fd_set		rfds;
-	int			readPipe;
-	int			pmPipe = pgStatPmPipe[0];
-	int			maxfd;
-	int			nready;
-	int			len = 0;
-	struct timeval timeout;
-	struct timeval next_statwrite;
-	bool		need_statwrite;
-	HASHCTL		hash_ctl;
+	IsUnderPostmaster = true;	/* we are a postmaster subprocess now */
 
-	/*
-	 * Close the writing end of the postmaster pipe, so we'll see it
-	 * closing when the postmaster terminates and can terminate as well.
-	 */
-	closesocket(pgStatPmPipe[1]);
-	pgStatPmPipe[1] = -1;
+	MyProcPid = getpid();		/* reset MyProcPid */
+
+	/* Lose the postmaster's on-exit routines */
+	on_exit_reset();
 
 	/*
 	 * Ignore all signals usually bound to some action in the postmaster,
@@ -1275,6 +1339,31 @@ pgstat_main(void)
 	pqsignal(SIGTTOU, SIG_DFL);
 	pqsignal(SIGCONT, SIG_DFL);
 	pqsignal(SIGWINCH, SIG_DFL);
+}
+
+
+/* ----------
+ * pgstat_main() -
+ *
+ *	Start up the statistics collector itself.  This is the body of the
+ *	postmaster child process.
+ * ----------
+ */
+NON_EXEC_STATIC void
+pgstat_main(PGSTAT_FORK_ARGS)
+{
+	pgstat_mainInit(); /* Note: for *both* EXEC_BACKEND and regular cases */
+
+#ifdef EXEC_BACKEND
+	pgstat_parseArgs(argc,argv);
+#endif
+
+	/*
+	 * Close the writing end of the postmaster pipe, so we'll see it
+	 * closing when the postmaster terminates and can terminate as well.
+	 */
+	closesocket(pgStatPmPipe[1]);
+	pgStatPmPipe[1] = -1;
 
 	/*
 	 * Start a buffering process to read from the socket, so we have a
@@ -1305,9 +1394,12 @@ pgstat_main(void)
 
 		case 0:
 			/* child becomes collector process */
-			closesocket(pgStatPipe[1]);
-			closesocket(pgStatSock);
-			break;
+#ifdef EXEC_BACKEND
+			pgstat_exec(STAT_PROC_COLLECTOR);
+#else
+			pgstat_mainChild();
+#endif
+			exit(0);
 
 		default:
 			/* parent becomes buffer process */
@@ -1315,6 +1407,36 @@ pgstat_main(void)
 			pgstat_recvbuffer();
 			exit(0);
 	}
+}
+
+
+NON_EXEC_STATIC void
+pgstat_mainChild(PGSTAT_FORK_ARGS)
+{
+	PgStat_Msg	msg;
+	fd_set		rfds;
+	int			readPipe;
+	int			pmPipe;
+	int			maxfd;
+	int			nready;
+	int			len = 0;
+	struct timeval timeout;
+	struct timeval next_statwrite;
+	bool		need_statwrite;
+	HASHCTL		hash_ctl;
+
+#ifdef EXEC_BACKEND
+	MemoryContextInit(); /* before any elog'ing can occur */
+
+	pgstat_mainInit();
+	pgstat_parseArgs(argc,argv);
+#else
+	MyProcPid = getpid();		/* reset MyProcPid */
+#endif
+
+	closesocket(pgStatPipe[1]);
+	closesocket(pgStatSock);
+	pmPipe = pgStatPmPipe[0];
 
 	/*
 	 * In the child we can have default SIGCHLD handling (in case we want
@@ -1322,8 +1444,6 @@ pgstat_main(void)
 	 */
 	pqsignal(SIGCHLD, SIG_DFL);
 
-	MyProcPid = getpid();		/* reset MyProcPid */
-
 	/*
 	 * Identify myself via ps
 	 */
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index f0560ce6f7e..cd654e1ffcf 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.352 2003/12/20 17:31:21 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.353 2003/12/25 03:52:51 momjian Exp $
  *
  * NOTES
  *
@@ -289,6 +289,7 @@ static void RandomSalt(char *cryptSalt, char *md5Salt);
 static void SignalChildren(int signal);
 static int	CountChildren(void);
 static bool CreateOptsFile(int argc, char *argv[]);
+NON_EXEC_STATIC void SSDataBaseInit(int xlop);
 static pid_t SSDataBase(int xlop);
 static void
 postmaster_error(const char *fmt,...)
@@ -296,8 +297,8 @@ postmaster_error(const char *fmt,...)
 __attribute__((format(printf, 1, 2)));
 
 #ifdef EXEC_BACKEND
-static void
-write_backend_variables(pid_t pid, Port *port);
+void read_backend_variables(pid_t pid, Port *port);
+static void write_backend_variables(pid_t pid, Port *port);
 #endif
 
 #define StartupDataBase()		SSDataBase(BS_XLOG_STARTUP)
@@ -2848,9 +2849,46 @@ CountChildren(void)
 /*
  * Fire off a subprocess for startup/shutdown/checkpoint.
  *
- * Return value is subprocess' PID, or 0 if failed to start subprocess
+ * Return value of SSDataBase is subprocess' PID, or 0 if failed to start subprocess
  * (0 is returned only for checkpoint case).
  */
+NON_EXEC_STATIC void
+SSDataBaseInit(int xlop)
+{
+	const char *statmsg;
+
+	IsUnderPostmaster = true;		/* we are a postmaster subprocess
+									 * now */
+
+	/* Lose the postmaster's on-exit routines and port connections */
+	on_exit_reset();
+
+	/*
+	 * Identify myself via ps
+	 */
+	switch (xlop)
+	{
+		case BS_XLOG_STARTUP:
+			statmsg = "startup subprocess";
+			break;
+		case BS_XLOG_CHECKPOINT:
+			statmsg = "checkpoint subprocess";
+			break;
+		case BS_XLOG_BGWRITER:
+			statmsg = "bgwriter subprocess";
+			break;
+		case BS_XLOG_SHUTDOWN:
+			statmsg = "shutdown subprocess";
+			break;
+		default:
+			statmsg = "??? subprocess";
+			break;
+	}
+	init_ps_display(statmsg, "", "");
+	set_ps_display("");
+}
+
+
 static pid_t
 SSDataBase(int xlop)
 {
@@ -2876,16 +2914,11 @@ SSDataBase(int xlop)
 
 	if ((pid = fork()) == 0)	/* child */
 	{
-		const char *statmsg;
 		char	   *av[10];
 		int			ac = 0;
 		char		nbbuf[32];
 		char		xlbuf[32];
 
-#ifdef EXEC_BACKEND
-		char		pbuf[NAMEDATALEN + 256];
-#endif
-
 #ifdef LINUX_PROFILE
 		setitimer(ITIMER_PROF, &prof_itimer, NULL);
 #endif
@@ -2895,65 +2928,47 @@ SSDataBase(int xlop)
 		beos_backend_startup();
 #endif
 
-		IsUnderPostmaster = true;		/* we are a postmaster subprocess
-										 * now */
-
-		/* Lose the postmaster's on-exit routines and port connections */
-		on_exit_reset();
-
 		/* Close the postmaster's sockets */
 		ClosePostmasterPorts(true);
 
-		/*
-		 * Identify myself via ps
-		 */
-		switch (xlop)
-		{
-			case BS_XLOG_STARTUP:
-				statmsg = "startup subprocess";
-				break;
-			case BS_XLOG_CHECKPOINT:
-				statmsg = "checkpoint subprocess";
-				break;
-			case BS_XLOG_BGWRITER:
-				statmsg = "bgwriter subprocess";
-				break;
-			case BS_XLOG_SHUTDOWN:
-				statmsg = "shutdown subprocess";
-				break;
-			default:
-				statmsg = "??? subprocess";
-				break;
-		}
-		init_ps_display(statmsg, "", "");
-		set_ps_display("");
+#ifndef EXEC_BACKEND
+		SSDataBaseInit(xlop);
+#endif
 
 		/* Set up command-line arguments for subprocess */
 		av[ac++] = "postgres";
 
+#ifdef EXEC_BACKEND
+		av[ac++] = "-boot";
+#endif
+
 		snprintf(nbbuf, sizeof(nbbuf), "-B%d", NBuffers);
 		av[ac++] = nbbuf;
 
 		snprintf(xlbuf, sizeof(xlbuf), "-x%d", xlop);
 		av[ac++] = xlbuf;
 
-		av[ac++] = "-p";
 #ifdef EXEC_BACKEND
-		Assert(UsedShmemSegID != 0 && UsedShmemSegAddr != NULL);
-		/* database name at the end because it might contain commas */
-		snprintf(pbuf, sizeof(pbuf), "%lu,%p,%s",
-				 UsedShmemSegID, UsedShmemSegAddr, "template1");
-		av[ac++] = pbuf;
-#else
-		av[ac++] = "template1";
+		write_backend_variables(getpid(),NULL);
+
+		/* pass data dir before end of secure switches (-p) */
+		av[ac++] = "-D";
+		av[ac++] = DataDir;
 #endif
+		av[ac++] = "-p";
+		av[ac++] = "template1";
 
 		av[ac] = (char *) NULL;
 
 		Assert(ac < lengthof(av));
 
+#ifdef EXEC_BACKEND
+		if (execv(pg_pathname,av) == -1)
+			elog(FATAL,"unable to execv in SSDataBase: %m");
+#else
 		BootstrapMain(ac, av);
 		ExitPostmaster(0);
+#endif
 	}
 
 	/* in parent */
@@ -3107,17 +3122,17 @@ extern slock_t  *ProcStructLock;
 extern int	pgStatSock;
 
 #define write_var(var,fp) fwrite((void*)&(var),sizeof(var),1,fp)
-#define read_var(var,fp)  fread((void*)&(var),sizeof(var),1,fp);
+#define read_var(var,fp)  fread((void*)&(var),sizeof(var),1,fp)
 #define get_tmp_backend_file_name(buf,id)	\
-		do {								\
-			Assert(DataDir);				\
-			sprintf((buf),					\
-				"%s/%s/%s.backend_var.%d",	\
-				DataDir,					\
-				PG_TEMP_FILES_DIR,			\
-				PG_TEMP_FILE_PREFIX,		\
-				(id));						\
-		} while (0)
+do {								\
+	Assert(DataDir);				\
+	sprintf((buf),					\
+		"%s/%s/%s.backend_var.%d",	\
+		DataDir,					\
+		PG_TEMP_FILES_DIR,			\
+		PG_TEMP_FILE_PREFIX,		\
+		(id));						\
+} while (0)
 
 static void
 write_backend_variables(pid_t pid, Port *port)
@@ -3146,11 +3161,16 @@ write_backend_variables(pid_t pid, Port *port)
 	}
 
 	/* Write vars */
-	write_var(port->sock,fp);
-	write_var(port->proto,fp);
-	write_var(port->laddr,fp);
-	write_var(port->raddr,fp);
-	write_var(port->canAcceptConnections,fp);
+	if (port)
+	{
+		write_var(port->sock,fp);
+		write_var(port->proto,fp);
+		write_var(port->laddr,fp);
+		write_var(port->raddr,fp);
+		write_var(port->canAcceptConnections,fp);
+		write_var(port->cryptSalt,fp);
+		write_var(port->md5Salt,fp);
+	}
 	write_var(MyCancelKey,fp);
 
 	write_var(RedoRecPtr,fp);
@@ -3190,11 +3210,16 @@ read_backend_variables(pid_t pid, Port *port)
 	}
 
 	/* Read vars */
-	read_var(port->sock,fp);
-	read_var(port->proto,fp);
-	read_var(port->laddr,fp);
-	read_var(port->raddr,fp);
-	read_var(port->canAcceptConnections,fp);
+	if (port)
+	{
+		read_var(port->sock,fp);
+		read_var(port->proto,fp);
+		read_var(port->laddr,fp);
+		read_var(port->raddr,fp);
+		read_var(port->canAcceptConnections,fp);
+		read_var(port->cryptSalt,fp);
+		read_var(port->md5Salt,fp);
+	}
 	read_var(MyCancelKey,fp);
 
 	read_var(RedoRecPtr,fp);
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index a0256fb2aa3..dfd6d16cca2 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.142 2003/12/21 00:33:33 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.143 2003/12/25 03:52:51 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -122,20 +122,31 @@ ProcGlobalSemas(int maxBackends)
 void
 InitProcGlobal(int maxBackends)
 {
-	bool		found = false;
+	bool		foundProcGlobal, foundDummy;
 
 	/* Create or attach to the ProcGlobal shared structure */
 	ProcGlobal = (PROC_HDR *)
-		ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found);
+		ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &foundProcGlobal);
 
-	/* --------------------
-	 * We're the first - initialize.
-	 * XXX if found should ever be true, it is a sign of impending doom ...
-	 * ought to complain if so?
-	 * --------------------
+	/*
+	 * Create or attach to the PGPROC structures for dummy (checkpoint)
+	 * processes, too.	This does not get linked into the freeProcs
+	 * list.
 	 */
-	if (!found)
+	DummyProc = (PGPROC *)
+		ShmemInitStruct("DummyProc",sizeof(PGPROC) * NUM_DUMMY_PROCS, &foundDummy);
+
+	if (foundProcGlobal || foundDummy)
 	{
+		/* both should be present or neither */
+		Assert(foundProcGlobal && foundDummy);
+		return;
+	}
+	else
+	{
+		/*
+		 * We're the first - initialize.
+		 */
 		int			i;
 
 		ProcGlobal->freeProcs = INVALID_OFFSET;
@@ -159,16 +170,6 @@ InitProcGlobal(int maxBackends)
 			ProcGlobal->freeProcs = MAKE_OFFSET(proc);
 		}
 
-		/*
-		 * Pre-allocate a PGPROC structure for dummy (checkpoint)
-		 * processes, too.	This does not get linked into the freeProcs
-		 * list.
-		 */
-		DummyProc = (PGPROC *) ShmemAlloc(sizeof(PGPROC) * NUM_DUMMY_PROCS);
-		if (!DummyProc)
-			ereport(FATAL,
-					(errcode(ERRCODE_OUT_OF_MEMORY),
-					 errmsg("out of shared memory")));
 		MemSet(DummyProc, 0, sizeof(PGPROC) * NUM_DUMMY_PROCS);
 		for (i = 0; i < NUM_DUMMY_PROCS; i++)
 		{
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 66f6dc063c8..c7252637e94 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.380 2003/12/20 17:31:21 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.381 2003/12/25 03:52:51 momjian Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -2063,7 +2063,7 @@ PostgresMain(int argc, char *argv[], const char *username)
 	 *
 	 * If we are running under the postmaster, this is done already.
 	 */
-	if (!IsUnderPostmaster /* when exec || ExecBackend */)
+	if (!IsUnderPostmaster || ExecBackend)
 		MemoryContextInit();
 
 	set_ps_display("startup");
@@ -2076,7 +2076,7 @@ PostgresMain(int argc, char *argv[], const char *username)
 	Noversion = false;
 	EchoQuery = false;
 
-	if (!IsUnderPostmaster /* when exec || ExecBackend */ )
+	if (!IsUnderPostmaster)
 	{
 		InitializeGUCOptions();
 		potential_DataDir = getenv("PGDATA");
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 7628955d437..7ff9dc465b7 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -5,7 +5,7 @@
  *
  *	Copyright (c) 2001-2003, PostgreSQL Global Development Group
  *
- *	$PostgreSQL: pgsql/src/include/pgstat.h,v 1.17 2003/11/29 22:40:53 pgsql Exp $
+ *	$PostgreSQL: pgsql/src/include/pgstat.h,v 1.18 2003/12/25 03:52:51 momjian Exp $
  * ----------
  */
 #ifndef PGSTAT_H
@@ -326,6 +326,18 @@ typedef union PgStat_Msg
 } PgStat_Msg;
 
 
+#ifdef EXEC_BACKEND
+typedef enum STATS_PROCESS_TYPE
+{
+	STAT_PROC_BUFFER,
+	STAT_PROC_COLLECTOR
+} STATS_PROCESS_TYPE;
+#define PGSTAT_FORK_ARGS int argc, char *argv[]
+#else
+#define PGSTAT_FORK_ARGS void
+#endif
+
+
 /* ----------
  * GUC parameters
  * ----------
@@ -342,6 +354,17 @@ extern bool pgstat_collect_blocklevel;
  */
 extern bool pgstat_is_running;
 
+
+/* ----------
+ * Functions called from main
+ * ----------
+ */
+#ifdef EXEC_BACKEND
+extern void pgstat_main(PGSTAT_FORK_ARGS);
+extern void pgstat_mainChild(PGSTAT_FORK_ARGS);
+#endif
+
+
 /* ----------
  * Functions called from postmaster
  * ----------
-- 
GitLab