From 3f3421f90523d12139fc47e5ba025cc9683f2679 Mon Sep 17 00:00:00 2001
From: Tatsuo Ishii <ishii@postgresql.org>
Date: Sun, 9 Jan 2000 12:13:24 +0000
Subject: [PATCH] Move SetPidFile() and firends to utils/init/miscinit.c so
 that tcop/postgres.c can use them. Now we have an interlock between
 postmaster and postgres.

---
 src/backend/postmaster/postmaster.c | 192 ++++++++--------------------
 1 file changed, 50 insertions(+), 142 deletions(-)

diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 67db5dec115..884563f4a02 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.132 2000/01/07 09:28:03 ishii Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.133 2000/01/09 12:13:24 ishii Exp $
  *
  * NOTES
  *
@@ -92,17 +92,6 @@
 #include "utils/trace.h"
 #include "version.h"
 
-/* 
- * "postmaster.pid" is a file containing postmaster's pid, being
- * created uder $PGDATA upon postmaster's starting up. When postmaster
- * shuts down, it will be unlinked. The purpose of the file includes:
- *
- * (1) supplying neccessary information to stop/restart postmaster
- * (2) preventing another postmaster process starting while it has
- *     already started
-*/
-#define PIDFNAME	"postmaster.pid"
-
 /*
  * "postmaster.opts" is a file containing options for postmaser.
  * pg_ctl will use it to restart postmaster.
@@ -250,11 +239,6 @@ static bool		FatalError = false;
 
 static unsigned int random_seed = 0;
 
-/*
- * Path to pid file. Exitpostmaster() remember it to unlink the file.
- */
-static char PidFile[MAXPGPATH];
-
 extern char *optarg;
 extern int	optind,
 			opterr;
@@ -282,9 +266,7 @@ static long 	PostmasterRandom(void);
 static void 	RandomSalt(char *salt);
 static void 	SignalChildren(SIGNAL_ARGS);
 static int		CountChildren(void);
-static void	UnlinkPidFile(void);
-static void	SetPidFname(char *datadir);
-static int SetPidFile(pid_t pid, char *progname, int port, char *datadir,
+static int SetOptsFile(char *progname, int port, char *datadir,
 		      int assert, int nbuf, char *execfile,
 		      int debuglvl, int netserver,
 #ifdef USE_SSL
@@ -657,8 +639,9 @@ PostmasterMain(int argc, char *argv[])
 		/*
 		 * create pid file. if the file has already existed, exits.
 		 */
-		if (SetPidFile(
-		       getpid(),	/* postmaster process id */
+	  SetPidFname(DataDir);
+	  if (SetPidFile(getpid()) == 0) {
+	    if (SetOptsFile(
 		       progname,	/* postmaster executable file */
 		       PostPortName,	/* port number */
 		       DataDir,		/* PGDATA */
@@ -675,13 +658,22 @@ PostmasterMain(int argc, char *argv[])
 		       silentflag,	/* -S: detach tty */
 		       SendStop,	/* -s: send SIGSTOP */
 		       original_extraoptions	/* options for backend */
-		       )
-		  ) {
-			ExitPostmaster(1);
-			return 0;	/* not reached */
-		}
+		       ) != 0) {
+		    UnlinkPidFile();
+		    ExitPostmaster(1);
+		    return 0;	/* not reached */
+	    }
+	  }
+	  else {
+	    ExitPostmaster(1);
+	    return 0;	/* not reached */
+	  }
+	    
+	  /*
+	   * register clean up proc
+	   */
+	  on_proc_exit(UnlinkPidFile, NULL);
 	}
-
 	/*
 	 * Set up signal handlers for the postmaster process.
 	 */
@@ -715,17 +707,19 @@ pmdaemonize(char *extraoptions)
 	int			i;
 	pid_t	pid;
 
+	SetPidFname(DataDir);
+
 	pid = fork();
 	if (pid == -1) {
 		perror("Failed to fork postmaster");
 		ExitPostmaster(1);
 		return;	/* not reached */
 	} else if (pid) {	/* parent */
-		/*
-		 * create pid file. if the file has already existed, exits.
-		 */
-		if (SetPidFile(
-		       pid,		/* postmaster process id */
+	  /*
+	   * create pid file. if the file has already existed, exits.
+	   */
+	  if (SetPidFile(pid) == 0) {
+	    if (SetOptsFile(
 		       progname,	/* postmaster executable file */
 		       PostPortName,	/* port number */
 		       DataDir,		/* PGDATA */
@@ -742,17 +736,27 @@ pmdaemonize(char *extraoptions)
 		       1,		/* -S: detach tty */
 		       SendStop,	/* -s: send SIGSTOP */
 		       extraoptions	/* options for backend */
-		       )
-		) {
-			/*
-			 * Failed to create pid file. kill the child and
-			 * exit now.
-			 */
-			kill(pid, SIGTERM);
-			ExitPostmaster(1);
-			return;	/* not reached */
-		}
-		_exit(0);
+		       ) != 0) {
+	      /*
+	       * Failed to create opts file. kill the child and
+	       * exit now.
+	       */
+	      UnlinkPidFile();
+	      kill(pid, SIGTERM);
+	      ExitPostmaster(1);
+	      return;	/* not reached */
+	    }
+	    _exit(0);
+	  }
+	  else {
+	      /*
+	       * Failed to create pid file. kill the child and
+	       * exit now.
+	       */
+	      kill(pid, SIGTERM);
+	      ExitPostmaster(1);
+	      return;	/* not reached */
+	  }
 	}
 
 /* GH: If there's no setsid(), we hopefully don't need silent mode.
@@ -779,7 +783,6 @@ pmdaemonize(char *extraoptions)
 	/*
 	 * register clean up proc
 	 */
-	SetPidFname(DataDir);
 	on_proc_exit(UnlinkPidFile, NULL);
 }
 
@@ -2179,25 +2182,9 @@ SSDataBase(bool startup)
 }
 
 /*
- * Remove the pid file. This function is called from proc_exit.
- */
-static void UnlinkPidFile(void)
-{
-	unlink(PidFile);
-}
-
-/*
- * Set path to the pid file
- */
-static void SetPidFname(char * datadir)
-{
-	snprintf(PidFile, sizeof(PidFile), "%s/%s", datadir, PIDFNAME);
-}
-
-/*
- * Create the pid file
+ * Create the opts file
  */
-static int SetPidFile(pid_t pid, char *progname, int port, char *datadir,
+static int SetOptsFile(char *progname, int port, char *datadir,
 		      int assert, int nbuf, char *execfile,
 		      int debuglvl, int netserver,
 #ifdef USE_SSL
@@ -2208,81 +2195,9 @@ static int SetPidFile(pid_t pid, char *progname, int port, char *datadir,
 {
 	int fd;
 	char optsfile[MAXPGPATH];
-	char pidstr[32];
-	int len;
-	pid_t post_pid;
 	char opts[1024];
 	char buf[1024];
 
-	/*
-	 * Creating pid file
-	 */
-	SetPidFname(datadir);
-	fd = open(PidFile, O_RDWR | O_CREAT | O_EXCL, 0600);
-	if (fd < 0) {
-		/*
-		 * Couldn't create the pid file. Probably
-		 * it already exists. Read the file to see if the process
-		 * actually exists
-		 */
-		fd = open(PidFile, O_RDONLY, 0600);
-		if (fd < 0) {
-			fprintf(stderr, "Can't create/read pid file: %s\n", PidFile);
-			fprintf(stderr, "Please check the permission and try again.\n");
-			return(-1);
-		}
-
-		if ((len = read(fd, pidstr, sizeof(pidstr)-1)) < 0) {
-			fprintf(stderr, "Can't create/read pid file: %s\n", PidFile);
-			fprintf(stderr, "Please check the permission and try again.\n");
-			close(fd);
-			return(-1);
-		}
-		close(fd);
-
-		/*
-		 * Check to see if the process actually exists
-		 */
-		pidstr[len] = '\0';
-		post_pid = (pid_t)atoi(pidstr);
-
-		if (post_pid == 0 || (post_pid > 0 && kill(post_pid, 0) < 0)) {
-			/*
-			 * No, the process did not exist. Unlink
-			 * the file and try to create it
-			 */
-			if (unlink(PidFile) < 0) {
-				fprintf(stderr, "Can't remove pidfile: %s\n", PidFile);
-				fprintf(stderr, "The file seems accidently left, but I couldn't remove it.\n");
-				fprintf(stderr, "Please remove the file by hand and try again.\n");
-				return(-1);
-			}
-			fd = open(PidFile, O_RDWR | O_CREAT | O_EXCL, 0600);
-			if (fd < 0) {
-				fprintf(stderr, "Can't create pidfile: %s\n", PidFile);
-				fprintf(stderr, "Please check the permission and try again.\n");
-				return(-1);
-			}
-		} else {
-			/*
-			 * Another postmaster is running
-			 */
-			fprintf(stderr, "Can't create pidfile: %s\n", PidFile);
-			fprintf(stderr, "Is another postmaster (pid: %s) running?\n", pidstr);
-			return(-1);
-		}
-	}
-
-	sprintf(pidstr, "%d", pid);
-	if (write(fd, pidstr, strlen(pidstr)) != strlen(pidstr)) {
-		fprintf(stderr,"Write to pid file failed\n");
-		fprintf(stderr, "Please check the permission and try again.\n");
-		close(fd);
-		unlink(PidFile);
-		return(-1);
-	}
-	close(fd);
-
 	/*
 	 * Creating opts file
 	 */
@@ -2290,7 +2205,6 @@ static int SetPidFile(pid_t pid, char *progname, int port, char *datadir,
 	fd = open(optsfile, O_RDWR | O_TRUNC | O_CREAT, 0600);
 	if (fd < 0) {
 		fprintf(stderr, "Can't create optsfile:%s", optsfile);
-		unlink(PidFile);
 		return(-1);
 	}
 	snprintf(opts, sizeof(opts), "%s\n-p %d\n-D %s\n",progname, port, datadir);
@@ -2340,16 +2254,10 @@ static int SetPidFile(pid_t pid, char *progname, int port, char *datadir,
 
 	if (write(fd, opts, strlen(opts)) != strlen(opts)) {
 		perror("Writing to opts file failed");
-		unlink(PidFile);
 		close(fd);
 		return(-1);
 	}
 	close(fd);
 
-	/*
-	 * register clean up proc
-	 */
-	on_proc_exit(UnlinkPidFile, NULL);
-
 	return(0);
 }
-- 
GitLab