]> granicus.if.org Git - postgresql/commitdiff
Work around unfortunate getppid() behavior on BSD-ish systems.
authorRobert Haas <rhaas@postgresql.org>
Tue, 21 Dec 2010 11:30:32 +0000 (06:30 -0500)
committerRobert Haas <rhaas@postgresql.org>
Tue, 21 Dec 2010 11:30:32 +0000 (06:30 -0500)
On MacOS X, and apparently also on other BSD-derived systems, attaching
a debugger causes getppid() to return the pid of the debugging process
rather than the actual parent PID.  As a result, debugging the
autovacuum launcher, startup process, or WAL sender on such systems
causes it to exit, because the previous coding of PostmasterIsAlive()
detects postmaster death by testing whether getppid() == PostmasterPid.

Work around that behavior by checking the return value of getppid()
more carefully.  If it's PostmasterPid, the postmaster must be alive;
if it's 1, assume the postmaster is dead.  If it's any other value,
assume we've been debugged and fall through to the less-reliable
kill() test.

Review by Tom Lane.

src/backend/storage/ipc/pmsignal.c

index 53aa9aaf70adfaea4a6ead05f33974cdf2322247..d2d6fa46877598f8a642d5a354e82c51934e6590 100644 (file)
@@ -260,22 +260,30 @@ PostmasterIsAlive(bool amDirectChild)
 #ifndef WIN32
        if (amDirectChild)
        {
+               pid_t   ppid = getppid();
+
+               /* If the postmaster is still our parent, it must be alive. */
+               if (ppid == PostmasterPid)
+                       return true;
+
+               /* If the init process is our parent, postmaster must be dead. */
+               if (ppid == 1)
+                       return false;
+
                /*
-                * If the postmaster is alive, we'll still be its child.  If it's
-                * died, we'll be reassigned as a child of the init process.
-                */
-               return (getppid() == PostmasterPid);
-       }
-       else
-       {
-               /*
-                * Use kill() to see if the postmaster is still alive.  This can
-                * sometimes give a false positive result, since the postmaster's PID
-                * may get recycled, but it is good enough for existing uses by
-                * indirect children.
+                * If we get here, our parent process is neither the postmaster nor
+                * init.  This can occur on BSD and MacOS systems if a debugger has
+                * been attached.  We fall through to the less-reliable kill() method.
                 */
-               return (kill(PostmasterPid, 0) == 0);
        }
+
+       /*
+        * Use kill() to see if the postmaster is still alive.  This can
+        * sometimes give a false positive result, since the postmaster's PID
+        * may get recycled, but it is good enough for existing uses by
+        * indirect children and in debugging environments.
+        */
+       return (kill(PostmasterPid, 0) == 0);
 #else                                                  /* WIN32 */
        return (WaitForSingleObject(PostmasterHandle, 0) == WAIT_TIMEOUT);
 #endif   /* WIN32 */