
$FreeBSD$

--- src/bin/pg_ctl/pg_ctl.c.orig
+++ src/bin/pg_ctl/pg_ctl.c
@@ -27,6 +27,7 @@
 #include <signal.h>
 #include <time.h>
 #include <sys/types.h>
+#include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <unistd.h>
@@ -155,10 +156,10 @@
 
 static pgpid_t get_pgpid(void);
 static char **readfile(const char *path);
-static pgpid_t start_postmaster(void);
+static pgpid_t start_postmaster(int *spair);
 static void read_post_opts(void);
 
-static PGPing test_postmaster_connection(pgpid_t pm_pid, bool do_checkpoint);
+static PGPing test_postmaster_connection(pgpid_t pm_pid, int *spair, bool do_checkpoint);
 static bool postmaster_is_alive(pid_t pid);
 
 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
@@ -414,7 +415,7 @@
  * "postmasterProcess", which the caller should close when done with it.
  */
 static pgpid_t
-start_postmaster(void)
+start_postmaster(int *spair)
 {
 	char		cmd[MAXPGPATH];
 
@@ -425,6 +426,11 @@
 	fflush(stdout);
 	fflush(stderr);
 
+	if (socketpair(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, spair) == -1) {
+		write_stderr(_("%s: could not start server: %s\n"),
+				progname, strerror(errno));
+		exit(1);
+	}
 	pm_pid = fork();
 	if (pm_pid < 0)
 	{
@@ -436,10 +442,12 @@
 	if (pm_pid > 0)
 	{
 		/* fork succeeded, in parent */
+		close(spair[0]);
 		return pm_pid;
 	}
 
 	/* fork succeeded, in child */
+	close(spair[1]);
 
 	/*
 	 * Since there might be quotes to handle here, it is easier simply to pass
@@ -509,7 +517,7 @@
  * manager checkpoint, it's got nothing to do with database checkpoints!!
  */
 static PGPing
-test_postmaster_connection(pgpid_t pm_pid, bool do_checkpoint)
+test_postmaster_connection(pgpid_t pm_pid, int *spair, bool do_checkpoint)
 {
 	PGPing		ret = PQPING_NO_RESPONSE;
 	char		connstr[MAXPGPATH * 2 + 256];
@@ -580,12 +588,7 @@
 					pmpid = atol(optlines[LOCK_FILE_LINE_PID - 1]);
 					pmstart = atol(optlines[LOCK_FILE_LINE_START_TIME - 1]);
 					if (pmstart >= start_time - 2 &&
-#ifndef WIN32
-						pmpid == pm_pid
-#else
-					/* Windows can only reject standalone-backend PIDs */
 						pmpid > 0
-#endif
 						)
 					{
 						/*
@@ -675,10 +678,11 @@
 		 */
 #ifndef WIN32
 		{
-			int			exitstatus;
+			char			fake_buf[16];
 
-			if (waitpid((pid_t) pm_pid, &exitstatus, WNOHANG) == (pid_t) pm_pid)
+			if (read(spair[1], fake_buf, sizeof(fake_buf)) == 0) {
 				return PQPING_NO_RESPONSE;
+			}
 		}
 #else
 		if (WaitForSingleObject(postmasterProcess, 0) == WAIT_OBJECT_0)
@@ -847,6 +851,9 @@
 {
 	pgpid_t		old_pid = 0;
 	pgpid_t		pm_pid;
+	int		pm_spair[2];
+
+	pm_spair[0] = pm_spair[1] = -1;
 
 	if (ctl_command != RESTART_COMMAND)
 	{
@@ -886,13 +893,13 @@
 	}
 #endif
 
-	pm_pid = start_postmaster();
+	pm_pid = start_postmaster(pm_spair);
 
 	if (do_wait)
 	{
 		print_msg(_("waiting for server to start..."));
 
-		switch (test_postmaster_connection(pm_pid, false))
+		switch (test_postmaster_connection(pm_pid, pm_spair, false))
 		{
 			case PQPING_OK:
 				print_msg(_(" done\n"));
@@ -1528,7 +1535,7 @@
 	if (do_wait)
 	{
 		write_eventlog(EVENTLOG_INFORMATION_TYPE, _("Waiting for server startup...\n"));
-		if (test_postmaster_connection(postmasterPID, true) != PQPING_OK)
+		if (test_postmaster_connection(postmasterPID, NULL, true) != PQPING_OK)
 		{
 			write_eventlog(EVENTLOG_ERROR_TYPE, _("Timed out waiting for server startup\n"));
 			pgwin32_SetServiceStatus(SERVICE_STOPPED);
