aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/ipc
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2011-07-08 18:27:49 +0300
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2011-07-08 18:44:07 +0300
commit89fd72cbf26f5d2e3d86ab19c1ead73ab8fac0fe (patch)
treefa0605f7ec1ff3a798b1c22fd847185158288a8b /src/backend/storage/ipc
parent9598afa3b0f7a7fdcf3740173346950b2bd5942c (diff)
downloadpostgresql-89fd72cbf26f5d2e3d86ab19c1ead73ab8fac0fe.tar.gz
postgresql-89fd72cbf26f5d2e3d86ab19c1ead73ab8fac0fe.zip
Introduce a pipe between postmaster and each backend, which can be used to
detect postmaster death. Postmaster keeps the write-end of the pipe open, so when it dies, children get EOF in the read-end. That can conveniently be waited for in select(), which allows eliminating some of the polling loops that check for postmaster death. This patch doesn't yet change all the loops to use the new mechanism, expect a follow-on patch to do that. This changes the interface to WaitLatch, so that it takes as argument a bitmask of events that it waits for. Possible events are latch set, timeout, postmaster death, and socket becoming readable or writeable. The pipe method behaves slightly differently from the kill() method previously used in PostmasterIsAlive() in the case that postmaster has died, but its parent has not yet read its exit code with waitpid(). The pipe returns EOF as soon as the process dies, but kill() continues to return true until waitpid() has been called (IOW while the process is a zombie). Because of that, change PostmasterIsAlive() to use the pipe too, otherwise WaitLatch() would return immediately with WL_POSTMASTER_DEATH, while PostmasterIsAlive() would claim it's still alive. That could easily lead to busy-waiting while postmaster is in zombie state. Peter Geoghegan with further changes by me, reviewed by Fujii Masao and Florian Pflug.
Diffstat (limited to 'src/backend/storage/ipc')
-rw-r--r--src/backend/storage/ipc/pmsignal.c41
1 files changed, 13 insertions, 28 deletions
diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c
index 306e3f9a216..eea95b7d060 100644
--- a/src/backend/storage/ipc/pmsignal.c
+++ b/src/backend/storage/ipc/pmsignal.c
@@ -267,42 +267,27 @@ MarkPostmasterChildInactive(void)
/*
* PostmasterIsAlive - check whether postmaster process is still alive
- *
- * amDirectChild should be passed as "true" by code that knows it is
- * executing in a direct child process of the postmaster; pass "false"
- * if an indirect child or not sure. The "true" case uses a faster and
- * more reliable test, so use it when possible.
*/
bool
-PostmasterIsAlive(bool amDirectChild)
+PostmasterIsAlive(void)
{
#ifndef WIN32
- if (amDirectChild)
- {
- pid_t ppid = getppid();
+ char c;
+ ssize_t rc;
- /* If the postmaster is still our parent, it must be alive. */
- if (ppid == PostmasterPid)
+ rc = read(postmaster_alive_fds[POSTMASTER_FD_WATCH], &c, 1);
+ if (rc < 0)
+ {
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
return true;
-
- /* If the init process is our parent, postmaster must be dead. */
- if (ppid == 1)
- return false;
-
- /*
- * 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.
- */
+ else
+ elog(FATAL, "read on postmaster death monitoring pipe failed: %m");
}
+ else if (rc > 0)
+ elog(FATAL, "unexpected data in postmaster death monitoring pipe");
+
+ return false;
- /*
- * 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 */