]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Make WL_POSTMASTER_DEATH level-triggered on kqueue builds.
authorThomas Munro <tmunro@postgresql.org>
Wed, 14 Oct 2020 22:31:20 +0000 (11:31 +1300)
committerThomas Munro <tmunro@postgresql.org>
Wed, 14 Oct 2020 22:42:17 +0000 (11:42 +1300)
If WaitEventSetWait() reports that the postmaster has gone away, later
calls to WaitEventSetWait() should continue to report that.  Otherwise
further waits that occur in the proc_exit() path after we already
noticed the postmaster's demise could block forever.

Back-patch to 13, where the kqueue support landed.

Reported-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/3624029.1602701929%40sss.pgh.pa.us

src/backend/storage/ipc/latch.c

index 91fa4b619b8c5c96cb99e7d3407d98686dd44ca1..256cc60a24292aba47b06977f29fbd52a5845ee3 100644 (file)
@@ -1429,7 +1429,10 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
                timeout_p = &timeout;
        }
 
-       /* Report events discovered by WaitEventAdjustKqueue(). */
+       /*
+        * Report postmaster events discovered by WaitEventAdjustKqueue() or an
+        * earlier call to WaitEventSetWait().
+        */
        if (unlikely(set->report_postmaster_not_running))
        {
                if (set->exit_on_postmaster_death)
@@ -1500,6 +1503,13 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
                                 cur_kqueue_event->filter == EVFILT_PROC &&
                                 (cur_kqueue_event->fflags & NOTE_EXIT) != 0)
                {
+                       /*
+                        * The kernel will tell this kqueue object only once about the exit
+                        * of the postmaster, so let's remember that for next time so that
+                        * we provide level-triggered semantics.
+                        */
+                       set->report_postmaster_not_running = true;
+
                        if (set->exit_on_postmaster_death)
                                proc_exit(1);
                        occurred_events->fd = PGINVALID_SOCKET;