]> granicus.if.org Git - postgresql/commitdiff
Add HOLD/RESUME_INTERRUPTS in HandleCatchupInterrupt/HandleNotifyInterrupt.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 13 Dec 2013 19:05:27 +0000 (14:05 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 13 Dec 2013 19:05:27 +0000 (14:05 -0500)
This prevents a possible longjmp out of the signal handler if a timeout
or SIGINT occurs while something within the handler has transiently set
ImmediateInterruptOK.  For safety we must hold off the timeout or cancel
error until we're back in mainline, or at least till we reach the end of
the signal handler when ImmediateInterruptOK was true at entry.  This
syncs these functions with the logic now present in handle_sig_alarm.

AFAICT there is no live bug here in 9.0 and up, because I don't think we
currently can wait for any heavyweight lock inside these functions, and
there is no other code (except read-from-client) that will turn on
ImmediateInterruptOK.  However, that was not true pre-9.0: in older
branches ProcessIncomingNotify might block trying to lock pg_listener, and
then a SIGINT could lead to undesirable control flow.  It might be all
right anyway given the relatively narrow code ranges in which NOTIFY
interrupts are enabled, but for safety's sake I'm back-patching this.

src/backend/commands/async.c
src/backend/storage/ipc/sinval.c

index 8db6f7e3e826aa5a901d7c3a79539e2bfef2f8c4..0022ad27adbbffe7aafe3b0fd840efbdba61393f 100644 (file)
@@ -1673,11 +1673,15 @@ HandleNotifyInterrupt(void)
 
                /*
                 * We may be called while ImmediateInterruptOK is true; turn it off
-                * while messing with the NOTIFY state.  (We would have to save and
-                * restore it anyway, because PGSemaphore operations inside
-                * ProcessIncomingNotify() might reset it.)
+                * while messing with the NOTIFY state.  This prevents problems if
+                * SIGINT or similar arrives while we're working.  Just to be real
+                * sure, bump the interrupt holdoff counter as well.  That way, even
+                * if something inside ProcessIncomingNotify() transiently sets
+                * ImmediateInterruptOK (eg while waiting on a lock), we won't get
+                * interrupted until we're done with the notify interrupt.
                 */
                ImmediateInterruptOK = false;
+               HOLD_INTERRUPTS();
 
                /*
                 * I'm not sure whether some flavors of Unix might allow another
@@ -1707,8 +1711,10 @@ HandleNotifyInterrupt(void)
                }
 
                /*
-                * Restore ImmediateInterruptOK, and check for interrupts if needed.
+                * Restore the holdoff level and ImmediateInterruptOK, and check for
+                * interrupts if needed.
                 */
+               RESUME_INTERRUPTS();
                ImmediateInterruptOK = save_ImmediateInterruptOK;
                if (save_ImmediateInterruptOK)
                        CHECK_FOR_INTERRUPTS();
index 79fe5480076d0be41c91c216cf7245e043c2d906..3f4f6dbd557a964719f8d8e211b44747fa17c9d0 100644 (file)
@@ -174,11 +174,15 @@ HandleCatchupInterrupt(void)
 
                /*
                 * We may be called while ImmediateInterruptOK is true; turn it off
-                * while messing with the catchup state.  (We would have to save and
-                * restore it anyway, because PGSemaphore operations inside
-                * ProcessCatchupEvent() might reset it.)
+                * while messing with the catchup state.  This prevents problems if
+                * SIGINT or similar arrives while we're working.  Just to be real
+                * sure, bump the interrupt holdoff counter as well.  That way, even
+                * if something inside ProcessCatchupEvent() transiently sets
+                * ImmediateInterruptOK (eg while waiting on a lock), we won't get
+                * interrupted until we're done with the catchup interrupt.
                 */
                ImmediateInterruptOK = false;
+               HOLD_INTERRUPTS();
 
                /*
                 * I'm not sure whether some flavors of Unix might allow another
@@ -202,8 +206,10 @@ HandleCatchupInterrupt(void)
                }
 
                /*
-                * Restore ImmediateInterruptOK, and check for interrupts if needed.
+                * Restore the holdoff level and ImmediateInterruptOK, and check for
+                * interrupts if needed.
                 */
+               RESUME_INTERRUPTS();
                ImmediateInterruptOK = save_ImmediateInterruptOK;
                if (save_ImmediateInterruptOK)
                        CHECK_FOR_INTERRUPTS();