Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Fix race condition at backend exit when deleting element in syncrep queue
authorMichael Paquier <michael@paquier.xyz>
Fri, 1 Nov 2019 13:38:55 +0000 (22:38 +0900)
committerMichael Paquier <michael@paquier.xyz>
Fri, 1 Nov 2019 13:38:55 +0000 (22:38 +0900)
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

index 7003cb525f44bf53a94cf97bb3a3f49c03e5bdec..262d324fb1b4075f5449fae7a8d28ae92a3e56f7 100644 (file)
@@ -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);
    }
 }