From dad8e410d0c4329ec68392c442e1f9dafc8ec17c Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 4 Aug 2001 00:14:43 +0000
Subject: [PATCH] Fix handling of SIGCHLD, per recent pghackers discussion: on
 some platforms system(2) gets confused unless the signal handler is set to
 SIG_DFL, not SIG_IGN.  pgstats.c now uses pqsignal() as it should, not
 signal().  Also, arrange for the stats collector process to show a reasonable
 ID in 'ps', rather than looking like a postmaster.

---
 src/backend/bootstrap/bootstrap.c   |   6 +-
 src/backend/commands/dbcommands.c   |   9 +-
 src/backend/postmaster/pgstat.c     | 128 ++++++++++++++++------------
 src/backend/postmaster/postmaster.c |   6 +-
 src/backend/tcop/postgres.c         |  12 +--
 src/include/pgstat.h                |   4 +-
 6 files changed, 92 insertions(+), 73 deletions(-)

diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 7fc54779680..56009217090 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
- *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.112 2001/07/16 05:06:57 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.113 2001/08/04 00:14:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -310,13 +310,15 @@ BootstrapMain(int argc, char *argv[])
 		pqsignal(SIGINT, SIG_IGN);		/* ignore query-cancel */
 		pqsignal(SIGTERM, die);
 		pqsignal(SIGQUIT, quickdie);
+		pqsignal(SIGALRM, SIG_IGN);
+		pqsignal(SIGPIPE, SIG_IGN);
 		pqsignal(SIGUSR1, SIG_IGN);
 		pqsignal(SIGUSR2, SIG_IGN);
 
 		/*
 		 * Reset some signals that are accepted by postmaster but not here
 		 */
-		pqsignal(SIGCHLD, SIG_IGN);
+		pqsignal(SIGCHLD, SIG_DFL);
 		pqsignal(SIGTTIN, SIG_DFL);
 		pqsignal(SIGTTOU, SIG_DFL);
 		pqsignal(SIGCONT, SIG_DFL);
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index dca75bd71d9..16b1241a027 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.76 2001/07/02 20:50:46 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.77 2001/08/04 00:14:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -58,7 +58,6 @@ createdb(const char *dbname, const char *dbpath,
 	char	   *target_dir;
 	char		src_loc[MAXPGPATH];
 	char		buf[2 * MAXPGPATH + 100];
-	int			ret;
 	bool		use_super,
 				use_createdb;
 	Oid			src_dboid;
@@ -195,9 +194,7 @@ createdb(const char *dbname, const char *dbpath,
 	/* Copy the template database to the new location */
 	snprintf(buf, sizeof(buf), "cp -r '%s' '%s'", src_loc, target_dir);
 
-	ret = system(buf);
-	/* Some versions of SunOS seem to return ECHILD after a system() call */
-	if (ret != 0 && errno != ECHILD)
+	if (system(buf) != 0)
 	{
 		if (remove_dbdirs(nominal_loc, alt_loc))
 			elog(ERROR, "CREATE DATABASE: could not initialize database directory");
@@ -557,7 +554,7 @@ remove_dbdirs(const char *nominal_loc, const char *alt_loc)
 
 	snprintf(buf, sizeof(buf), "rm -rf '%s'", target_dir);
 
-	if (system(buf) != 0 && errno != ECHILD)
+	if (system(buf) != 0)
 	{
 		elog(NOTICE, "database directory '%s' could not be removed",
 			 target_dir);
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 8efda5c90ff..6c571aaebcf 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -16,41 +16,41 @@
  *
  *	Copyright (c) 2001, PostgreSQL Global Development Group
  *
- *	$Id: pgstat.c,v 1.4 2001/07/05 15:19:40 wieck Exp $
+ *	$Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.5 2001/08/04 00:14:43 tgl Exp $
  * ----------
  */
 #include "postgres.h"
 
 #include <unistd.h>
 #include <fcntl.h>
-
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-
 #include <errno.h>
 #include <signal.h>
 
+#include "access/xact.h"
+#include "access/heapam.h"
+#include "catalog/catname.h"
+#include "catalog/pg_shadow.h"
+#include "catalog/pg_database.h"
+#include "libpq/pqsignal.h"
 #include "miscadmin.h"
 #include "utils/memutils.h"
 #include "storage/backendid.h"
 #include "utils/rel.h"
 #include "utils/hsearch.h"
+#include "utils/ps_status.h"
 #include "utils/syscache.h"
-#include "access/xact.h"
-#include "access/heapam.h"
-#include "catalog/catname.h"
-#include "catalog/pg_shadow.h"
-#include "catalog/pg_database.h"
 
 #include "pgstat.h"
 
 
 /* ----------
- * Global data
+ * GUC parameters
  * ----------
  */
 bool	pgstat_collect_startcollector	= true;
@@ -95,8 +95,8 @@ static char					pgStat_fname[MAXPGPATH];
  * Local function forward declarations
  * ----------
  */
-static void		pgstat_main(void);
-static void		pgstat_recvbuffer(void);
+static void		pgstat_main(int real_argc, char *real_argv[]);
+static void		pgstat_recvbuffer(int real_argc, char *real_argv[]);
 
 static int		pgstat_add_backend(PgStat_MsgHdr *msg);
 static void		pgstat_sub_backend(int procpid);
@@ -227,11 +227,14 @@ pgstat_init(void)
  * pgstat_start() -
  *
  *	Called from postmaster at startup or after an existing collector
- *	died. Fire up a fresh statistics collector.
+ *	died.  Fire up a fresh statistics collector.
+ *
+ *	The process' original argc and argv are passed, because they are
+ *	needed by init_ps_display() on some platforms.
  * ----------
  */
 int
-pgstat_start(void)
+pgstat_start(int real_argc, char *real_argv[])
 {
 	/*
 	 * Do nothing if no collector needed
@@ -267,7 +270,8 @@ pgstat_start(void)
 			return 0;
 	}
 
-	pgstat_main();
+	pgstat_main(real_argc, real_argv);
+
 	exit(0);
 }
 
@@ -989,15 +993,6 @@ pgstat_fetch_stat_numbackends(void)
 
 
 
-
-
-
-
-
-
-
-
-
 /* ------------------------------------------------------------
  * Local support functions follow
  * ------------------------------------------------------------
@@ -1053,7 +1048,7 @@ pgstat_send(void *msg, int len)
  * ----------
  */
 static void
-pgstat_main(void)
+pgstat_main(int real_argc, char *real_argv[])
 {
 	PgStat_Msg	msg;
 	fd_set			rfds;
@@ -1076,27 +1071,22 @@ pgstat_main(void)
 	/*
 	 * Ignore all signals usually bound to some action in the postmaster
 	 */
-	signal(SIGHUP, SIG_IGN);
-	signal(SIGINT, SIG_IGN);
-	signal(SIGQUIT, SIG_IGN);
-	signal(SIGTERM, SIG_IGN);
-	signal(SIGALRM, SIG_IGN);
-	signal(SIGPIPE, SIG_IGN);
-	signal(SIGUSR1, SIG_IGN);
-	signal(SIGUSR2, SIG_IGN);
-	signal(SIGCHLD, SIG_IGN);
-	signal(SIGTTIN, SIG_IGN);
-	signal(SIGTTOU, SIG_IGN);
-	signal(SIGWINCH, SIG_IGN);
-
-	/*
-	 * Write the initial status file right at startup
-	 */
-	gettimeofday(&next_statwrite, NULL);
-	need_statwrite = TRUE;
-
-	/*
-	 * Now we start the buffer process to read from the socket, so
+	pqsignal(SIGHUP, SIG_IGN);
+	pqsignal(SIGINT, SIG_IGN);
+	pqsignal(SIGTERM, SIG_IGN);
+	pqsignal(SIGQUIT, SIG_IGN);
+	pqsignal(SIGALRM, SIG_IGN);
+	pqsignal(SIGPIPE, SIG_IGN);
+	pqsignal(SIGUSR1, SIG_IGN);
+	pqsignal(SIGUSR2, SIG_IGN);
+	pqsignal(SIGCHLD, SIG_DFL);
+	pqsignal(SIGTTIN, SIG_DFL);
+	pqsignal(SIGTTOU, SIG_DFL);
+	pqsignal(SIGCONT, SIG_DFL);
+	pqsignal(SIGWINCH, SIG_DFL);
+
+	/*
+	 * Start a buffering subprocess to read from the socket, so
 	 * we have a little more time to process incoming messages.
 	 */
 	if (pipe(pgStatPipe) < 0)
@@ -1107,19 +1097,38 @@ pgstat_main(void)
 
 	switch(fork())
 	{
-		case -1:	perror("PGSTAT: fork(2)");
-					exit(1);
+		case -1:
+			perror("PGSTAT: fork(2)");
+			exit(1);
 
-		case 0:		close(pgStatPipe[0]);
-					signal(SIGPIPE, SIG_DFL);
-					pgstat_recvbuffer();
-					exit(2);
+		case 0:
+			close(pgStatPipe[0]);
+			/* child process should die if can't pipe to parent collector */
+			pqsignal(SIGPIPE, SIG_DFL);
+			pgstat_recvbuffer(real_argc, real_argv);
+			exit(2);
 
-		default:	close(pgStatPipe[1]);
-					close(pgStatSock);
-					break;
+		default:
+			close(pgStatPipe[1]);
+			close(pgStatSock);
+			break;
 	}
 
+	/*
+	 * Identify myself via ps
+	 *
+	 * WARNING: On some platforms the environment will be moved around to
+	 * make room for the ps display string.
+	 */
+	init_ps_display(real_argc, real_argv, "stats collector process", "", "");
+	set_ps_display("");
+
+	/*
+	 * Arrange to write the initial status file right away
+	 */
+	gettimeofday(&next_statwrite, NULL);
+	need_statwrite = TRUE;
+
 	/*
 	 * Read in an existing statistics stats file or initialize the
 	 * stats to zero.
@@ -1358,7 +1367,7 @@ pgstat_main(void)
  * ----------
  */
 static void
-pgstat_recvbuffer(void)
+pgstat_recvbuffer(int real_argc, char *real_argv[])
 {
 	fd_set				rfds;
 	fd_set				wfds;
@@ -1373,6 +1382,15 @@ pgstat_recvbuffer(void)
 	int					fromlen;
 	int					overflow = 0;
 
+	/*
+	 * Identify myself via ps
+	 *
+	 * WARNING: On some platforms the environment will be moved around to
+	 * make room for the ps display string.
+	 */
+	init_ps_display(real_argc, real_argv, "stats buffer process", "", "");
+	set_ps_display("");
+
 	/*
 	 * Allocate the message buffer
 	 */
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index fb51695e98b..511f9bc0ee6 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.233 2001/07/31 22:55:45 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.234 2001/08/04 00:14:43 tgl Exp $
  *
  * NOTES
  *
@@ -696,7 +696,7 @@ PostmasterMain(int argc, char *argv[])
 	 */
 	if (pgstat_init() < 0)
 		ExitPostmaster(1);
-	if (pgstat_start() < 0)
+	if (pgstat_start(real_argc, real_argv) < 0)
 		ExitPostmaster(1);
 
 	/*
@@ -1488,7 +1488,7 @@ reaper(SIGNAL_ARGS)
 		{
 			fprintf(stderr, "%s: Performance collector exited with status %d\n",
 					progname, exitstatus);
-			pgstat_start();
+			pgstat_start(real_argc, real_argv);
 			continue;
 		}
 
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 4083d0cd020..ac701704c16 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.229 2001/07/31 22:55:45 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.230 2001/08/04 00:14:43 tgl Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -1102,7 +1102,9 @@ usage(char *progname)
  * ----------------------------------------------------------------
  */
 int
-PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const char *username)
+PostgresMain(int argc, char *argv[],
+			 int real_argc, char *real_argv[],
+			 const char *username)
 {
 	int			flag;
 
@@ -1535,15 +1537,15 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 	 */
 	pqsignal(SIGPIPE, SIG_IGN);
 	pqsignal(SIGUSR1, SIG_IGN); /* this signal available for use */
+
 	pqsignal(SIGUSR2, Async_NotifyHandler);		/* flush also sinval cache */
 	pqsignal(SIGFPE, FloatExceptionHandler);
-	pqsignal(SIGCHLD, SIG_IGN); /* ignored (may get this in system()
-								 * calls) */
 
 	/*
 	 * Reset some signals that are accepted by postmaster but not by
 	 * backend
 	 */
+	pqsignal(SIGCHLD, SIG_DFL);	/* system() requires this on some platforms */
 	pqsignal(SIGTTIN, SIG_DFL);
 	pqsignal(SIGTTOU, SIG_DFL);
 	pqsignal(SIGCONT, SIG_DFL);
@@ -1711,7 +1713,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 	if (!IsUnderPostmaster)
 	{
 		puts("\nPOSTGRES backend interactive interface ");
-		puts("$Revision: 1.229 $ $Date: 2001/07/31 22:55:45 $\n");
+		puts("$Revision: 1.230 $ $Date: 2001/08/04 00:14:43 $\n");
 	}
 
 	/*
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 51bb00dc16b..fc9dc43326a 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -5,7 +5,7 @@
  *
  *	Copyright (c) 2001, PostgreSQL Global Development Group
  *
- *  $Id: pgstat.h,v 1.4 2001/07/05 15:19:40 wieck Exp $
+ *  $Id: pgstat.h,v 1.5 2001/08/04 00:14:43 tgl Exp $
  * ----------
  */
 #ifndef PGSTAT_H
@@ -336,7 +336,7 @@ extern bool		pgstat_collect_blocklevel;
  * ----------
  */
 extern int		pgstat_init(void);
-extern int		pgstat_start(void);
+extern int		pgstat_start(int real_argc, char *real_argv[]);
 extern int		pgstat_ispgstat(int pid);
 extern void		pgstat_beterm(int pid);
 
-- 
GitLab