Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Munro2018-11-23 07:16:41 +0000
committerThomas Munro2018-11-23 07:46:34 +0000
commitcfdf4dc4fc9635ac8bf6eaaa5dbbcd364ab29f0c (patch)
treec1e3c40912c5f9274fb9381bea1082f6a2cc2296 /src/backend/postmaster
parentd392e9bdea957964e1fa6a5481e5adb5904d759a (diff)
Add WL_EXIT_ON_PM_DEATH pseudo-event.
Users of the WaitEventSet and WaitLatch() APIs can now choose between asking for WL_POSTMASTER_DEATH and then handling it explicitly, or asking for WL_EXIT_ON_PM_DEATH to trigger immediate exit on postmaster death. This reduces code duplication, since almost all callers want the latter. Repair all code that was previously ignoring postmaster death completely, or requesting the event but ignoring it, or requesting the event but then doing an unconditional PostmasterIsAlive() call every time through its event loop (which is an expensive syscall on platforms for which we don't have USE_POSTMASTER_DEATH_SIGNAL support). Assert that callers of WaitLatchXXX() under the postmaster remember to ask for either WL_POSTMASTER_DEATH or WL_EXIT_ON_PM_DEATH, to prevent future bugs. The only process that doesn't handle postmaster death is syslogger. It waits until all backends holding the write end of the syslog pipe (including the postmaster) have closed it by exiting, to be sure to capture any parting messages. By using the WaitEventSet API directly it avoids the new assertion, and as a by-product it may be slightly more efficient on platforms that have epoll(). Author: Thomas Munro Reviewed-by: Kyotaro Horiguchi, Heikki Linnakangas, Tom Lane Discussion: https://postgr.es/m/CAEepm%3D1TCviRykkUb69ppWLr_V697rzd1j3eZsRMmbXvETfqbQ%40mail.gmail.com, https://postgr.es/m/CAEepm=2LqHzizbe7muD7-2yHUbTOoF7Q+qkSD5Q41kuhttRTwA@mail.gmail.com
Diffstat (limited to 'src/backend/postmaster')
-rw-r--r--src/backend/postmaster/autovacuum.c16
-rw-r--r--src/backend/postmaster/bgwriter.c11
-rw-r--r--src/backend/postmaster/checkpointer.c16
-rw-r--r--src/backend/postmaster/pgarch.c4
-rw-r--r--src/backend/postmaster/syslogger.c38
-rw-r--r--src/backend/postmaster/walwriter.c16
6 files changed, 40 insertions, 61 deletions
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 31e98db9d69..2d5086d4062 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -628,7 +628,6 @@ AutoVacLauncherMain(int argc, char *argv[])
struct timeval nap;
TimestampTz current_time = 0;
bool can_launch;
- int rc;
/*
* This loop is a bit different from the normal use of WaitLatch,
@@ -644,23 +643,16 @@ AutoVacLauncherMain(int argc, char *argv[])
* Wait until naptime expires or we get some type of signal (all the
* signal handlers will wake us by calling SetLatch).
*/
- rc = WaitLatch(MyLatch,
- WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- (nap.tv_sec * 1000L) + (nap.tv_usec / 1000L),
- WAIT_EVENT_AUTOVACUUM_MAIN);
+ (void) WaitLatch(MyLatch,
+ WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
+ (nap.tv_sec * 1000L) + (nap.tv_usec / 1000L),
+ WAIT_EVENT_AUTOVACUUM_MAIN);
ResetLatch(MyLatch);
/* Process sinval catchup interrupts that happened while sleeping */
ProcessCatchupInterrupt();
- /*
- * Emergency bailout if postmaster has died. This is to avoid the
- * necessity for manual cleanup of all postmaster children.
- */
- if (rc & WL_POSTMASTER_DEATH)
- proc_exit(1);
-
/* the normal shutdown case */
if (got_SIGTERM)
break;
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index 54a042843da..bd8dc61182d 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -335,7 +335,7 @@ BackgroundWriterMain(void)
* normal operation.
*/
rc = WaitLatch(MyLatch,
- WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
+ WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
BgWriterDelay /* ms */ , WAIT_EVENT_BGWRITER_MAIN);
/*
@@ -362,20 +362,13 @@ BackgroundWriterMain(void)
StrategyNotifyBgWriter(MyProc->pgprocno);
/* Sleep ... */
rc = WaitLatch(MyLatch,
- WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
+ WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
BgWriterDelay * HIBERNATE_FACTOR,
WAIT_EVENT_BGWRITER_HIBERNATE);
/* Reset the notification request in case we timed out */
StrategyNotifyBgWriter(-1);
}
- /*
- * Emergency bailout if postmaster has died. This is to avoid the
- * necessity for manual cleanup of all postmaster children.
- */
- if (rc & WL_POSTMASTER_DEATH)
- exit(1);
-
prev_hibernate = can_hibernate;
}
}
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 9eac86b554b..b9c118e1560 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -340,7 +340,6 @@ CheckpointerMain(void)
pg_time_t now;
int elapsed_secs;
int cur_timeout;
- int rc;
/* Clear any already-pending wakeups */
ResetLatch(MyLatch);
@@ -541,17 +540,10 @@ CheckpointerMain(void)
cur_timeout = Min(cur_timeout, XLogArchiveTimeout - elapsed_secs);
}
- rc = WaitLatch(MyLatch,
- WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- cur_timeout * 1000L /* convert to ms */ ,
- WAIT_EVENT_CHECKPOINTER_MAIN);
-
- /*
- * Emergency bailout if postmaster has died. This is to avoid the
- * necessity for manual cleanup of all postmaster children.
- */
- if (rc & WL_POSTMASTER_DEATH)
- exit(1);
+ (void) WaitLatch(MyLatch,
+ WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
+ cur_timeout * 1000L /* convert to ms */ ,
+ WAIT_EVENT_CHECKPOINTER_MAIN);
}
}
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 0ebd63650c6..844b9d1b0e9 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -390,6 +390,8 @@ pgarch_MainLoop(void)
WAIT_EVENT_ARCHIVER_MAIN);
if (rc & WL_TIMEOUT)
wakened = true;
+ if (rc & WL_POSTMASTER_DEATH)
+ time_to_stop = true;
}
else
wakened = true;
@@ -400,7 +402,7 @@ pgarch_MainLoop(void)
* or after completing one more archiving cycle after receiving
* SIGUSR2.
*/
- } while (PostmasterIsAlive() && !time_to_stop);
+ } while (!time_to_stop);
}
/*
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index 35755138890..fbeee311092 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -168,6 +168,7 @@ SysLoggerMain(int argc, char *argv[])
char *currentLogFilename;
int currentLogRotationAge;
pg_time_t now;
+ WaitEventSet *wes;
now = MyStartTime;
@@ -294,13 +295,29 @@ SysLoggerMain(int argc, char *argv[])
*/
whereToSendOutput = DestNone;
+ /*
+ * Set up a reusable WaitEventSet object we'll use to wait for our latch,
+ * and (except on Windows) our socket.
+ *
+ * Unlike all other postmaster child processes, we'll ignore postmaster
+ * death because we want to collect final log output from all backends and
+ * then exit last. We'll do that by running until we see EOF on the
+ * syslog pipe, which implies that all other backends have exited
+ * (including the postmaster).
+ */
+ wes = CreateWaitEventSet(CurrentMemoryContext, 2);
+ AddWaitEventToSet(wes, WL_LATCH_SET, PGINVALID_SOCKET, MyLatch, NULL);
+#ifndef WIN32
+ AddWaitEventToSet(wes, WL_SOCKET_READABLE, syslogPipe[0], NULL, NULL);
+#endif
+
/* main worker loop */
for (;;)
{
bool time_based_rotation = false;
int size_rotation_for = 0;
long cur_timeout;
- int cur_flags;
+ WaitEvent event;
#ifndef WIN32
int rc;
@@ -436,25 +453,18 @@ SysLoggerMain(int argc, char *argv[])
}
else
cur_timeout = 0;
- cur_flags = WL_TIMEOUT;
}
else
- {
cur_timeout = -1L;
- cur_flags = 0;
- }
/*
* Sleep until there's something to do
*/
#ifndef WIN32
- rc = WaitLatchOrSocket(MyLatch,
- WL_LATCH_SET | WL_SOCKET_READABLE | cur_flags,
- syslogPipe[0],
- cur_timeout,
- WAIT_EVENT_SYSLOGGER_MAIN);
+ rc = WaitEventSetWait(wes, cur_timeout, &event, 1,
+ WAIT_EVENT_SYSLOGGER_MAIN);
- if (rc & WL_SOCKET_READABLE)
+ if (rc == 1 && event.events == WL_SOCKET_READABLE)
{
int bytesRead;
@@ -501,10 +511,8 @@ SysLoggerMain(int argc, char *argv[])
*/
LeaveCriticalSection(&sysloggerSection);
- (void) WaitLatch(MyLatch,
- WL_LATCH_SET | cur_flags,
- cur_timeout,
- WAIT_EVENT_SYSLOGGER_MAIN);
+ (void) WaitEventSetWait(wes, cur_timeout, &event, 1,
+ WAIT_EVENT_SYSLOGGER_MAIN);
EnterCriticalSection(&sysloggerSection);
#endif /* WIN32 */
diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c
index 3e09827854d..0ae733e886a 100644
--- a/src/backend/postmaster/walwriter.c
+++ b/src/backend/postmaster/walwriter.c
@@ -223,7 +223,6 @@ WalWriterMain(void)
for (;;)
{
long cur_timeout;
- int rc;
/*
* Advertise whether we might hibernate in this cycle. We do this
@@ -276,17 +275,10 @@ WalWriterMain(void)
else
cur_timeout = WalWriterDelay * HIBERNATE_FACTOR;
- rc = WaitLatch(MyLatch,
- WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- cur_timeout,
- WAIT_EVENT_WAL_WRITER_MAIN);
-
- /*
- * Emergency bailout if postmaster has died. This is to avoid the
- * necessity for manual cleanup of all postmaster children.
- */
- if (rc & WL_POSTMASTER_DEATH)
- exit(1);
+ (void) WaitLatch(MyLatch,
+ WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
+ cur_timeout,
+ WAIT_EVENT_WAL_WRITER_MAIN);
}
}