summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2009-03-31 05:18:39 +0000
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2009-03-31 05:18:39 +0000
commit6bd988355758569e4bce8b600d8175c94fa8d78a (patch)
treedb3becbc7192e0663a2b3a58d5916f11f26576e5
parent781e1557e10532969a74deaca0736cc1ef1b5e41 (diff)
Fix a rare race condition when commit_siblings > 0 and a transaction commits
at the same instant as a new backend is spawned. Since CountActiveBackends() doesn't hold ProcArrayLock, it needs to be prepared for the case that a pointer at the end of the proc array is still NULL even though numProcs says it should be valid, since it doesn't hold ProcArrayLock. Backpatch to 8.1. 8.0 and earlier had this right, but it was broken in the split of PGPROC and sinval shared memory arrays. Per report and proposal by Marko Kreen.
-rw-r--r--src/backend/storage/ipc/procarray.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 575b138c435..a9ae969f31e 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -23,7 +23,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.40 2008/01/09 21:52:36 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.40.2.1 2009/03/31 05:18:39 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -198,6 +198,7 @@ ProcArrayRemove(PGPROC *proc, TransactionId latestXid)
if (arrayP->procs[index] == proc)
{
arrayP->procs[index] = arrayP->procs[arrayP->numProcs - 1];
+ arrayP->procs[arrayP->numProcs - 1] = NULL; /* for debugging */
arrayP->numProcs--;
LWLockRelease(ProcArrayLock);
return;
@@ -1089,6 +1090,20 @@ CountActiveBackends(void)
{
volatile PGPROC *proc = arrayP->procs[index];
+ /*
+ * Since we're not holding a lock, need to check that the pointer is
+ * valid. Someone holding the lock could have incremented numProcs
+ * already, but not yet inserted a valid pointer to the array.
+ *
+ * If someone just decremented numProcs, 'proc' could also point to a
+ * PGPROC entry that's no longer in the array. It still points to a
+ * PGPROC struct, though, because freed PGPPROC entries just go to
+ * the free list and are recycled. Its contents are nonsense in that
+ * case, but that's acceptable for this function.
+ */
+ if (proc != NULL)
+ continue;
+
if (proc == MyProc)
continue; /* do not count myself */
if (proc->pid == 0)