From 7bc76d51fbac35950ae5e5d05535bdc33f93b42c Mon Sep 17 00:00:00 2001
From: Simon Riggs <simon@2ndQuadrant.com>
Date: Mon, 19 Apr 2010 18:03:38 +0000
Subject: [PATCH] Check RecoveryInProgress() while holding ProcArrayLock during
 snapshots. This prevents a rare, yet possible race condition at the exact
 moment of transition from recovery to normal running.

---
 src/backend/storage/ipc/procarray.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index c79f25ecf10..a24b2b7c1ea 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.63 2010/04/18 18:05:55 sriggs Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.64 2010/04/19 18:03:38 sriggs Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1074,8 +1074,6 @@ GetSnapshotData(Snapshot snapshot)
 					 errmsg("out of memory")));
 	}
 
-	snapshot->takenDuringRecovery = RecoveryInProgress();
-
 	/*
 	 * It is sufficient to get shared lock on ProcArrayLock, even if we are
 	 * going to set MyProc->xmin.
@@ -1091,8 +1089,15 @@ GetSnapshotData(Snapshot snapshot)
 	globalxmin = xmin = xmax;
 
 	/*
-	 * If in recovery get any known assigned xids.
+	 * If we're in recovery then snapshot data comes from a different place,
+	 * so decide which route we take before grab the lock. It is possible
+	 * for recovery to end before we finish taking snapshot, and for newly
+	 * assigned transaction ids to be added to the procarray. Xmax cannot
+	 * change while we hold ProcArrayLock, so those newly added transaction
+	 * ids would be filtered away, so we need not be concerned about them.
 	 */
+	snapshot->takenDuringRecovery = RecoveryInProgress();
+
 	if (!snapshot->takenDuringRecovery)
 	{
 		/*
-- 
GitLab