From: Robert Haas Date: Tue, 5 Apr 2011 19:16:59 +0000 (-0400) Subject: Repair some flakiness in CheckTargetForConflictsIn. X-Git-Tag: REL9_1_BETA1~154 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=632f0faa7c975e8984ce0f1d6b631478e41a96c2;p=postgresql Repair some flakiness in CheckTargetForConflictsIn. When we release and reacquire SerializableXactHashLock, we must recheck whether an R/W conflict still needs to be flagged, because it could have changed under us in the meantime. And when we release the partition lock, we must re-walk the list of predicate locks from the beginning, because our pointer could get invalidated under us. Bug report #5952 by Yamamoto Takashi. Patch by Kevin Grittner. --- diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index 401acdb471..5096ea0c1c 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -3757,6 +3757,17 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag) LWLockRelease(partitionLock); LWLockRelease(SerializablePredicateLockListLock); LWLockAcquire(partitionLock, LW_SHARED); + + /* + * The list may have been altered by another process + * while we weren't holding the partition lock. Start + * over at the front. + */ + nextpredlock = (PREDICATELOCK *) + SHMQueueNext(&(target->predicateLocks), + &(target->predicateLocks), + offsetof(PREDICATELOCK, targetLink)); + LWLockAcquire(SerializableXactHashLock, LW_SHARED); } } @@ -3770,7 +3781,19 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag) LWLockRelease(SerializableXactHashLock); LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE); - FlagRWConflict(sxact, (SERIALIZABLEXACT *) MySerializableXact); + /* + * Re-check after getting exclusive lock because the other + * transaction may have flagged a conflict. + */ + if (!SxactIsRolledBack(sxact) + && (!SxactIsCommitted(sxact) + || TransactionIdPrecedes(GetTransactionSnapshot()->xmin, + sxact->finishedBefore)) + && !RWConflictExists(sxact, + (SERIALIZABLEXACT *) MySerializableXact)) + { + FlagRWConflict(sxact, (SERIALIZABLEXACT *) MySerializableXact); + } LWLockRelease(SerializableXactHashLock); LWLockAcquire(SerializableXactHashLock, LW_SHARED);