postgres.git / summary / log / commit / refs

commit    b99bfc3c96f16c4e08bc1276cee95f01bcc09bf3
Author:   Michael Paquier <michael@paquier.xyz>
Date:     Fri Nov 01 13:38:55 2019 +0000
First released in: 13.0, 9.4.25, 9.5.20, 9.6.16, 10.11, 11.6, 12.1

    Fix race condition at backend exit when deleting element in syncrep queue
    
    When a backend exits, it gets deleted from the syncrep queue if present.
    The queue was checked without SyncRepLock taken in exclusive mode, so it
    would have been possible for a backend to remove itself after a WAL
    sender already did the job.  Fix this issue based on a suggestion from
    Fujii Masao, by first checking the queue without the lock.  Then, if the
    backend is present in the queue, take the lock and perform an additional
    lookup check before doing the element deletion.
    
    Author: Dongming Liu
    Reviewed-by: Kyotaro Horiguchi, Fujii Masao, Michael Paquier
    Discussion: https://postgr.es/m/a0806273-8bbb-43b3-bbe1-c45a58f6ae21.lingce.ldm@alibaba-inc.com
    Backpatch-through: 9.4


src/backend/replication/syncrep.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index 7003cb525f4..262d324fb1b 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -362,10 +362,18 @@ SyncRepCancelWait(void) void SyncRepCleanupAtProcExit(void) { + /* + * First check if we are removed from the queue without the lock to not + * slow down backend exit. + */ if (!SHMQueueIsDetached(&(MyProc->syncRepLinks))) { LWLockAcquire(SyncRepLock, LW_EXCLUSIVE); - SHMQueueDelete(&(MyProc->syncRepLinks)); + + /* maybe we have just been removed, so recheck */ + if (!SHMQueueIsDetached(&(MyProc->syncRepLinks))) + SHMQueueDelete(&(MyProc->syncRepLinks)); + LWLockRelease(SyncRepLock); } } [parent: 82200115e055]