diff options
author | Robert Haas | 2011-04-05 19:16:59 +0000 |
---|---|---|
committer | Robert Haas | 2011-04-05 19:17:25 +0000 |
commit | 632f0faa7c975e8984ce0f1d6b631478e41a96c2 (patch) | |
tree | d6c8a3841563ed71b15a7de3823ae9d7e4eaee4a /src | |
parent | 38d15f16511cb9f75ed2b1e1f73117c1bc581538 (diff) |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/storage/lmgr/predicate.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index 401acdb4715..5096ea0c1c1 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); |