From: Robert Haas Date: Tue, 21 Dec 2010 11:30:32 +0000 (-0500) Subject: Work around unfortunate getppid() behavior on BSD-ish systems. X-Git-Tag: REL9_1_ALPHA3~33 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=24ecde7742cd4d7c781e6890b07571fff42b25dc;p=postgresql Work around unfortunate getppid() behavior on BSD-ish systems. 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. --- diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 53aa9aaf70..d2d6fa4687 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -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 */