diff --git a/contrib/start-scripts/freebsd b/contrib/start-scripts/freebsd
index 528fc776c7871e5965b978fed3db71a62f9a87f7..10ea48249863f91727789fc6c49d1c98c4ac9216 100644
--- a/contrib/start-scripts/freebsd
+++ b/contrib/start-scripts/freebsd
@@ -6,7 +6,7 @@
 # Created through merger of the Linux start script by Ryan Kirkpatrick
 # and the script in the FreeBSD ports collection.
 
-# $PostgreSQL: pgsql/contrib/start-scripts/freebsd,v 1.4 2004/10/01 18:30:21 tgl Exp $
+# $PostgreSQL: pgsql/contrib/start-scripts/freebsd,v 1.5 2009/08/27 16:59:38 tgl Exp $
 
 ## EDIT FROM HERE
 
@@ -27,9 +27,9 @@ PGLOG="$PGDATA/serverlog"
 # The path that is to be used for the script
 PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
 
-# What to use to start up the postmaster (we do NOT use pg_ctl for this,
-# as it adds no value and can cause the postmaster to misrecognize a stale
-# lock file)
+# What to use to start up the postmaster.  (If you want the script to wait
+# until the server has started, you could use "pg_ctl start -w" here.
+# But without -w, pg_ctl adds no value.)
 DAEMON="$prefix/bin/postmaster"
 
 # What to use to shut down the postmaster
diff --git a/contrib/start-scripts/linux b/contrib/start-scripts/linux
index f1feb34f94d29bd38d2adc8d47be138dac8ab018..6d6ff2aed9f9cbbacff27372d526686d5f6f008d 100644
--- a/contrib/start-scripts/linux
+++ b/contrib/start-scripts/linux
@@ -24,7 +24,7 @@
 
 # Original author:  Ryan Kirkpatrick <pgsql@rkirkpat.net>
 
-# $PostgreSQL: pgsql/contrib/start-scripts/linux,v 1.8 2006/07/13 14:44:33 petere Exp $
+# $PostgreSQL: pgsql/contrib/start-scripts/linux,v 1.9 2009/08/27 16:59:38 tgl Exp $
 
 ## EDIT FROM HERE
 
@@ -45,9 +45,9 @@ PGLOG="$PGDATA/serverlog"
 # The path that is to be used for the script
 PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
 
-# What to use to start up the postmaster (we do NOT use pg_ctl for this,
-# as it adds no value and can cause the postmaster to misrecognize a stale
-# lock file)
+# What to use to start up the postmaster.  (If you want the script to wait
+# until the server has started, you could use "pg_ctl start -w" here.
+# But without -w, pg_ctl adds no value.)
 DAEMON="$prefix/bin/postmaster"
 
 # What to use to shut down the postmaster
diff --git a/contrib/start-scripts/osx/PostgreSQL b/contrib/start-scripts/osx/PostgreSQL
index dc826837a3206a5d8311beec4d78837861512641..65150d0fd56af4f23f10fe05fa7dcc3cc258048a 100755
--- a/contrib/start-scripts/osx/PostgreSQL
+++ b/contrib/start-scripts/osx/PostgreSQL
@@ -68,9 +68,9 @@ ROTATESEC="604800"
 # The path that is to be used for the script
 PATH="$prefix/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
 
-# What to use to start up the postmaster (we do NOT use pg_ctl for this,
-# as it adds no value and can cause the postmaster to misrecognize a stale
-# lock file)
+# What to use to start up the postmaster.  (If you want the script to wait
+# until the server has started, you could use "pg_ctl start -w" here.
+# But without -w, pg_ctl adds no value.)
 DAEMON="$prefix/bin/postmaster"
 
 # What to use to shut down the postmaster
@@ -85,7 +85,7 @@ StartService () {
     if [ "${POSTGRESQL:=-NO-}" = "-YES-" ]; then
         ConsoleMessage "Starting PostgreSQL database server"
         if [ "${ROTATELOGS}" = "1" ]; then
-            sudo -u $PGUSER sh -c "${DAEMON} -D '${PGDATA}' 2>&1 | ${LOGUTIL} '${PGLOG}' ${ROTATESEC} &"
+            sudo -u $PGUSER sh -c "${DAEMON} -D '${PGDATA}' &" 2>&1 | ${LOGUTIL} '${PGLOG}' ${ROTATESEC} &
         else
             sudo -u $PGUSER sh -c "${DAEMON} -D '${PGDATA}' &" >>$PGLOG 2>&1
         fi
@@ -104,7 +104,7 @@ RestartService () {
 	sudo -u $PGUSER $PGCTL stop -D "$PGDATA" -s -m fast
 	# should match StartService:
         if [ "${ROTATELOGS}" = "1" ]; then
-            sudo -u $PGUSER sh -c "${DAEMON} -D '${PGDATA}' 2>&1 | ${LOGUTIL} '${PGLOG}' ${ROTATESEC} &"
+            sudo -u $PGUSER sh -c "${DAEMON} -D '${PGDATA}' &" 2>&1 | ${LOGUTIL} '${PGLOG}' ${ROTATESEC} &
         else
             sudo -u $PGUSER sh -c "${DAEMON} -D '${PGDATA}' &" >>$PGLOG 2>&1
         fi
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 0b004d7e5f0bb49aeb9fb5c3ef3bd6685b27856d..85f1507ba366a507d50ca37d7f4cee1290ab6830 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.176 2009/08/12 20:53:30 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.177 2009/08/27 16:59:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -683,7 +683,46 @@ CreateLockFile(const char *filename, bool amPostmaster,
 	int			len;
 	int			encoded_pid;
 	pid_t		other_pid;
-	pid_t		my_pid = getpid();
+	pid_t		my_pid,
+				my_p_pid,
+				my_gp_pid;
+	const char *envvar;
+
+	/*
+	 * If the PID in the lockfile is our own PID or our parent's or
+	 * grandparent's PID, then the file must be stale (probably left over from
+	 * a previous system boot cycle).  We need to check this because of the
+	 * likelihood that a reboot will assign exactly the same PID as we had in
+	 * the previous reboot, or one that's only one or two counts larger and
+	 * hence the lockfile's PID now refers to an ancestor shell process.  We
+	 * allow pg_ctl to pass down its parent shell PID (our grandparent PID)
+	 * via the environment variable PG_GRANDPARENT_PID; this is so that
+	 * launching the postmaster via pg_ctl can be just as reliable as
+	 * launching it directly.  There is no provision for detecting
+	 * further-removed ancestor processes, but if the init script is written
+	 * carefully then all but the immediate parent shell will be root-owned
+	 * processes and so the kill test will fail with EPERM.  Note that we
+	 * cannot get a false negative this way, because an existing postmaster
+	 * would surely never launch a competing postmaster or pg_ctl process
+	 * directly.
+	 */
+	my_pid = getpid();
+
+#ifndef WIN32
+	my_p_pid = getppid();
+#else
+	/*
+	 * Windows hasn't got getppid(), but doesn't need it since it's not
+	 * using real kill() either...
+	 */
+	my_p_pid = 0;
+#endif
+
+	envvar = getenv("PG_GRANDPARENT_PID");
+	if (envvar)
+		my_gp_pid = atoi(envvar);
+	else
+		my_gp_pid = 0;
 
 	/*
 	 * We need a loop here because of race conditions.	But don't loop forever
@@ -745,17 +784,11 @@ CreateLockFile(const char *filename, bool amPostmaster,
 		/*
 		 * Check to see if the other process still exists
 		 *
-		 * If the PID in the lockfile is our own PID or our parent's PID, then
-		 * the file must be stale (probably left over from a previous system
-		 * boot cycle).  We need this test because of the likelihood that a
-		 * reboot will assign exactly the same PID as we had in the previous
-		 * reboot.	Also, if there is just one more process launch in this
-		 * reboot than in the previous one, the lockfile might mention our
-		 * parent's PID.  We can reject that since we'd never be launched
-		 * directly by a competing postmaster.	We can't detect grandparent
-		 * processes unfortunately, but if the init script is written
-		 * carefully then all but the immediate parent shell will be
-		 * root-owned processes and so the kill test will fail with EPERM.
+		 * Per discussion above, my_pid, my_p_pid, and my_gp_pid can be
+		 * ignored as false matches.
+		 *
+		 * Normally kill() will fail with ESRCH if the given PID doesn't
+		 * exist.
 		 *
 		 * We can treat the EPERM-error case as okay because that error
 		 * implies that the existing process has a different userid than we
@@ -772,18 +805,9 @@ CreateLockFile(const char *filename, bool amPostmaster,
 		 * Unix socket file belonging to an instance of Postgres being run by
 		 * someone else, at least on machines where /tmp hasn't got a
 		 * stickybit.)
-		 *
-		 * Windows hasn't got getppid(), but doesn't need it since it's not
-		 * using real kill() either...
-		 *
-		 * Normally kill() will fail with ESRCH if the given PID doesn't
-		 * exist.
 		 */
-		if (other_pid != my_pid
-#ifndef WIN32
-			&& other_pid != getppid()
-#endif
-			)
+		if (other_pid != my_pid && other_pid != my_p_pid &&
+			other_pid != my_gp_pid)
 		{
 			if (kill(other_pid, 0) == 0 ||
 				(errno != ESRCH && errno != EPERM))
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index 40ede2c1a839bb9712df01a9dc7fd7e294c48587..ff8f4a2552321e27f76bbc9d5203d2e5aa207322 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -4,7 +4,7 @@
  *
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.111 2009/06/11 14:49:07 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.112 2009/08/27 16:59:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -672,6 +672,21 @@ do_start(void)
 		unlimit_core_size();
 #endif
 
+	/*
+	 * If possible, tell the postmaster our parent shell's PID (see the
+	 * comments in CreateLockFile() for motivation).  Windows hasn't got
+	 * getppid() unfortunately.
+	 */
+#ifndef WIN32
+	{
+		static char env_var[32];
+
+		snprintf(env_var, sizeof(env_var), "PG_GRANDPARENT_PID=%d",
+				 (int) getppid());
+		putenv(env_var);
+	}
+#endif
+
 	exitcode = start_postmaster();
 	if (exitcode != 0)
 	{