fix-GetOldestActiveTransactionId-race.patch

application/x-patch

Filename: fix-GetOldestActiveTransactionId-race.patch
Type: application/x-patch
Part: 0
Message: Race condition in GetOldestActiveTransactionId()

Patch

Format: unified
File+
src/backend/storage/ipc/procarray.c 5 5
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index e5d487d..de45c16 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -2097,13 +2097,13 @@ GetOldestActiveTransactionId(void)
 	LWLockAcquire(ProcArrayLock, LW_SHARED);
 
 	/*
-	 * It's okay to read nextXid without acquiring XidGenLock because (1) we
-	 * assume TransactionIds can be read atomically and (2) we don't care if
-	 * we get a slightly stale value.  It can't be very stale anyway, because
-	 * the LWLockAcquire above will have done any necessary memory
-	 * interlocking.
+	 * Acquire XidGenLock while we read nextXid, to make sure that all
+	 * XIDs < nextXid are already present in the proc array (or have
+	 * already completed), when we spin over it.
 	 */
+	LWLockAcquire(XidGenLock, LW_SHARED);
 	oldestRunningXid = ShmemVariableCache->nextXid;
+	LWLockRelease(XidGenLock);
 
 	/*
 	 * Spin over procArray collecting all xids and subxids.