mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
Clear async.c's isAdvancing flag when a notify read is aborted.
asyncQueueReadAllNotifications() sets our isAdvancing flag and clears it when done. But if we error out in between, for example on a cancel while waiting for a safe snapshot, the flag stays set and SignalBackends() never advances or wakes us again, so the queue tail stops moving. To fix, clear the flag in AtAbort_Notify(). (We need not worry about this in subtransaction abort, since asyncQueueReadAllNotifications() is only called in top-level transactions.) Author: shihao zhong <zhong950419@gmail.com> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://postgr.es/m/CAGRkXqQ1bmVwBw2CXiyZeWWP=XkHPXLPcQ7BSg2Q5JKSvDAnTA@mail.gmail.com Backpatch-through: 19
This commit is contained in:
@@ -2413,13 +2413,24 @@ SignalBackends(void)
|
||||
* This is called at transaction abort.
|
||||
*
|
||||
* Revert any staged listen/unlisten changes and clean up transaction state.
|
||||
* This only does anything if we abort after PreCommit_Notify has staged
|
||||
* some entries.
|
||||
*/
|
||||
void
|
||||
AtAbort_Notify(void)
|
||||
{
|
||||
/* Revert staged listen/unlisten changes */
|
||||
/*
|
||||
* If we failed during asyncQueueReadAllNotifications(), clear our
|
||||
* isAdvancing flag, else SignalBackends() would never wake us again.
|
||||
* Since only our own process changes this flag, it is safe to check it
|
||||
* without the lock.
|
||||
*/
|
||||
if (amRegisteredListener && QUEUE_BACKEND_IS_ADVANCING(MyProcNumber))
|
||||
{
|
||||
LWLockAcquire(NotifyQueueLock, LW_SHARED);
|
||||
QUEUE_BACKEND_IS_ADVANCING(MyProcNumber) = false;
|
||||
LWLockRelease(NotifyQueueLock);
|
||||
}
|
||||
|
||||
/* Revert any staged listen/unlisten changes */
|
||||
ApplyPendingListenActions(false);
|
||||
|
||||
/* If we're no longer listening on anything, unregister */
|
||||
|
||||
Reference in New Issue
Block a user