fix-PLT-links-before-unblocking-signals.patch
text/x-diff
Filename: fix-PLT-links-before-unblocking-signals.patch
Type: text/x-diff
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/postmaster/postmaster.c | 29 | 0 |
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 1664fcee2a..f9070da574 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -1728,6 +1728,33 @@ ServerLoop(void)
nSockets = initMasks(&readmask);
+ /*
+ * Issue a dummy select() call before we unblock signals. The point of
+ * this is that select() may be reached via a PLT indirection, and that
+ * indirection will need to be resolved on first use, and on some
+ * platforms the dynamic loader's resolution code takes a lock. If that
+ * lock is taken while signals are unblocked then we risk self-deadlock
+ * should a signal handler do anything that also needs the loader lock.
+ * This is a low-probability failure, since it can only happen if a signal
+ * arrives with just the right timing during the first pass through the
+ * server loop. However, it has been seen repeatedly on slow single-CPU
+ * machines.
+ *
+ * Likewise, issue a dummy pg_usleep() to ensure we've resolved any PLT
+ * indirections needed in the PM_WAIT_DEAD_END path. (The PG_SETMASK
+ * calls could also be at hazard, had we not issued one of those when
+ * blocking signals to begin with.)
+ */
+ {
+ struct timeval timeout0;
+
+ timeout0.tv_sec = 0;
+ timeout0.tv_usec = 0;
+ (void) select(0, NULL, NULL, NULL, &timeout0);
+ pg_usleep(0);
+ }
+
+ /* Main server loop begins here */
for (;;)
{
fd_set rmask;
@@ -1750,6 +1777,7 @@ ServerLoop(void)
{
PG_SETMASK(&UnBlockSig);
+ /* Add nothing else in this unblocked-signals section */
pg_usleep(100000L); /* 100 msec seems reasonable */
selres = 0;
@@ -1765,6 +1793,7 @@ ServerLoop(void)
PG_SETMASK(&UnBlockSig);
+ /* Add nothing else in this unblocked-signals section */
selres = select(nSockets, &rmask, NULL, NULL, &timeout);
PG_SETMASK(&BlockSig);