1
0
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:
Tom Lane
2026-10-22 12:26:20 -04:00
parent 5ffb8c7409
commit 871dee0ccb

View File

@@ -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 */