]> granicus.if.org Git - postgresql/commitdiff
Set the process latch when processing recovery conflict interrupts.
authorAndres Freund <andres@anarazel.de>
Tue, 3 Jun 2014 12:02:54 +0000 (14:02 +0200)
committerAndres Freund <andres@anarazel.de>
Tue, 3 Jun 2014 12:19:29 +0000 (14:19 +0200)
Because RecoveryConflictInterrupt() didn't set the process latch
anything using the latter to wait for events didn't get notified about
recovery conflicts. Most latch users are never the target of recovery
conflicts, which explains the lack of reports about this until
now.
Since 9.3 two possible affected users exist though: The sql callable
pg_sleep() now uses latches to wait and background workers are
expected to use latches in their main loop. Both would currently wait
until the end of WaitLatch's timeout.

Fix by adding a SetLatch() to RecoveryConflictInterrupt(). It'd also
be possible to fix the issue by having each latch user set
set_latch_on_sigusr1. That seems failure prone and though, as most of
these callsites won't often receive recovery conflicts and thus will
likely only be tested against normal query cancels et al. It'd also be
unnecessarily verbose.

Backpatch to 9.1 where latches were introduced. Arguably 9.3 would be
sufficient, because that's where pg_sleep() was converted to waiting
on the latch and background workers got introduced; but there could be
user level code making use of the latch pre 9.3.

src/backend/tcop/postgres.c

index 3cdc0715ece1b4bd2c742b9bfa85f2b8bc5e987c..82a49c2e23885467a8726f90d5c316de6addd6e5 100644 (file)
@@ -2848,6 +2848,16 @@ RecoveryConflictInterrupt(ProcSignalReason reason)
                }
        }
 
+       /*
+        * Set the process latch. This function essentially emulates signal
+        * handlers like die() and StatementCancelHandler() and it seems prudent
+        * to behave similarly as they do. Alternatively all plain backend code
+        * waiting on that latch, expecting to get interrupted by query cancels et
+        * al., would also need to set set_latch_on_sigusr1.
+        */
+       if (MyProc)
+               SetLatch(&MyProc->procLatch);
+
        errno = save_errno;
 }