Commit 632f0faa authored by Robert Haas's avatar Robert Haas

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.
parent 38d15f16
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment