aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2019-11-01 22:38:45 +0900
committerMichael Paquier <michael@paquier.xyz>2019-11-01 22:38:45 +0900
commit7b8c2de64e66659115c1e4075c025d6392d659ef (patch)
treea48b9f0db50308dfc84ef7d78e2f4cb372490556
parent9de37ea65188167b0dc0acb3ce25f031c6cb4d79 (diff)
downloadpostgresql-7b8c2de64e66659115c1e4075c025d6392d659ef.tar.gz
postgresql-7b8c2de64e66659115c1e4075c025d6392d659ef.zip
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
-rw-r--r--src/backend/replication/syncrep.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c
index 577791f3d5f..864c6cba055 100644
--- a/src/backend/replication/syncrep.c
+++ b/src/backend/replication/syncrep.c
@@ -361,10 +361,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);
}
}