From 46c333a9638b329a3c8076d978f27c5b05c0d5f0 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Tue, 8 Mar 2011 21:01:29 +0200
Subject: [PATCH] Fix overly strict assertion in
 SummarizeOldestCommittedSxact(). There's a race condition where
 SummarizeOldestCommittedSxact() is called even though another backend already
 cleared out all finished sxact entries. That's OK,
 RegisterSerializableTransactionInt() can just retry getting a news xact slot
 from the available-list when that happens.

Reported by YAMAMOTO Takashi, bug #5918.
---
 src/backend/storage/lmgr/predicate.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index 15f0a64d3c2..870cf4277cf 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -1314,15 +1314,21 @@ SummarizeOldestCommittedSxact(void)
 
 	LWLockAcquire(SerializableFinishedListLock, LW_EXCLUSIVE);
 
-#ifdef TEST_OLDSERXID
+	/*
+	 * This function is only called if there are no sxact slots available.
+	 * Some of them must belong to old, already-finished transactions, so
+	 * there should be something in FinishedSerializableTransactions list
+	 * that we can summarize. However, there's a race condition: while we
+	 * were not holding any locks, a transaction might have ended and cleaned
+	 * up all the finished sxact entries already, freeing up their sxact
+	 * slots. In that case, we have nothing to do here. The caller will find
+	 * one of the slots released by the other backend when it retries.
+	 */
 	if (SHMQueueEmpty(FinishedSerializableTransactions))
 	{
 		LWLockRelease(SerializableFinishedListLock);
 		return;
 	}
-#else
-	Assert(!SHMQueueEmpty(FinishedSerializableTransactions));
-#endif
 
 	/*
 	 * Grab the first sxact off the finished list -- this will be the earliest
-- 
GitLab