From 6da05dd2c7efd5900905277d34172812cd59bde4 Mon Sep 17 00:00:00 2001 From: Simon Riggs Date: Fri, 2 Oct 2009 21:28:14 +0100 Subject: [PATCH] Resolve a race condition on update of ShmemVariableCache->latestCompletedXid, plus use XidGenLock during xact_redo_abort() as in xact_redo_commit(). Some changes direct from Heikki, others address code review comments from Heikki. --- src/backend/access/transam/xact.c | 21 +++++++-------------- src/backend/storage/ipc/procarray.c | 5 +++++ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 8c45738f14..d5a95c63c8 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -4607,10 +4607,7 @@ xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid, /* * Release locks, if any. We do this for both two phase and normal * one phase transactions. In effect we are ignoring the prepare - * phase and just going straight to lock release. This explains - * why the twophase_postcommit_standby_callbacks[] do not invoke - * a special routine to handle locks - that is performed here - * instead. + * phase and just going straight to lock release. */ RelationReleaseRecoveryLockTree(xid, xlrec->nsubxacts, sub_xids); } @@ -4629,15 +4626,6 @@ xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid, LWLockRelease(XidGenLock); } - /* Same here, don't use lock to test, but need one to modify */ - if (TransactionIdFollowsOrEquals(max_xid, - ShmemVariableCache->latestCompletedXid)) - { - LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); - ShmemVariableCache->latestCompletedXid = max_xid; - LWLockRelease(ProcArrayLock); - } - /* Make sure files supposed to be dropped are dropped */ for (i = 0; i < xlrec->nrels; i++) { @@ -4706,12 +4694,17 @@ xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid) } /* Make sure nextXid is beyond any XID mentioned in the record */ + /* We don't expect anyone else to modify nextXid, hence we + * don't need to hold a lock while checking this. We still acquire + * the lock to modify it, though. + */ if (TransactionIdFollowsOrEquals(max_xid, ShmemVariableCache->nextXid)) { + LWLockAcquire(XidGenLock, LW_EXCLUSIVE); ShmemVariableCache->nextXid = max_xid; - ShmemVariableCache->latestCompletedXid = ShmemVariableCache->nextXid; TransactionIdAdvance(ShmemVariableCache->nextXid); + LWLockRelease(XidGenLock); } /* Make sure files supposed to be dropped are dropped */ diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 0145ab6448..daee07b71f 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -2345,6 +2345,11 @@ ExpireTreeKnownAssignedTransactionIds(TransactionId xid, int nsubxids, TransactionIdPrecedes(procArray->lastOverflowedXid, max_xid)) procArray->lastOverflowedXid = max_xid; + /* Same here, don't use lock to test, but need one to modify */ + if (TransactionIdFollowsOrEquals(max_xid, + ShmemVariableCache->latestCompletedXid)) + ShmemVariableCache->latestCompletedXid = max_xid; + LWLockRelease(ProcArrayLock); } -- 2.39.5