mirror of
https://github.com/latentPrion/libspinscale.git
synced 2026-04-17 22:44:25 +00:00
Dbg:traceContinHistForDeadlock: consult LockUsageDesc::hasBeenReleased
Don't raise the alarm for a deadlock if the lock has already been released at the moment of checking.
This commit is contained in:
@@ -197,15 +197,52 @@ public:
|
|||||||
allLocksAcquired = false;
|
allLocksAcquired = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LockUsageDesc &getLockUsageDesc(const Qutex &criterionLock) const
|
std::optional<std::reference_wrapper<LockUsageDesc>>
|
||||||
|
findLockUsageDesc(const Qutex &criterionLock)
|
||||||
{
|
{
|
||||||
for (auto& lockUsageDesc : locks)
|
for (auto& lockUsageDesc : locks)
|
||||||
{
|
{
|
||||||
if (&lockUsageDesc.qutex.get() == &criterionLock) {
|
if (&lockUsageDesc.qutex.get() == &criterionLock) {
|
||||||
return lockUsageDesc;
|
return std::ref(lockUsageDesc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::reference_wrapper<const LockUsageDesc>>
|
||||||
|
findLockUsageDesc(const Qutex &criterionLock) const
|
||||||
|
{
|
||||||
|
for (const auto& lockUsageDesc : locks)
|
||||||
|
{
|
||||||
|
if (&lockUsageDesc.qutex.get() == &criterionLock) {
|
||||||
|
return std::cref(lockUsageDesc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
LockUsageDesc &getLockUsageDesc(const Qutex &criterionLock)
|
||||||
|
{
|
||||||
|
auto lockUsageDesc = findLockUsageDesc(criterionLock);
|
||||||
|
if (lockUsageDesc.has_value()) {
|
||||||
|
return lockUsageDesc->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should never happen if the LockSet is properly constructed
|
||||||
|
throw std::runtime_error(
|
||||||
|
std::string(__func__) +
|
||||||
|
": Qutex not found in this LockSet");
|
||||||
|
}
|
||||||
|
|
||||||
|
const LockUsageDesc &getLockUsageDesc(const Qutex &criterionLock) const
|
||||||
|
{
|
||||||
|
auto lockUsageDesc = findLockUsageDesc(criterionLock);
|
||||||
|
if (lockUsageDesc.has_value()) {
|
||||||
|
return lockUsageDesc->get();
|
||||||
|
}
|
||||||
|
|
||||||
// Should never happen if the LockSet is properly constructed
|
// Should never happen if the LockSet is properly constructed
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
std::string(__func__) +
|
std::string(__func__) +
|
||||||
@@ -225,8 +262,7 @@ public:
|
|||||||
": LockSet::releaseQutexEarly() called but allLocksAcquired is false");
|
": LockSet::releaseQutexEarly() called but allLocksAcquired is false");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& lockUsageDesc = const_cast<LockUsageDesc&>(
|
auto& lockUsageDesc = getLockUsageDesc(qutex);
|
||||||
getLockUsageDesc(qutex));
|
|
||||||
|
|
||||||
if (!lockUsageDesc.hasBeenReleased)
|
if (!lockUsageDesc.hasBeenReleased)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -335,11 +335,12 @@ SerializedAsynchronousContinuation<OriginalCbFnT>
|
|||||||
auto heldLockSet = currContin->getLockSet();
|
auto heldLockSet = currContin->getLockSet();
|
||||||
if (!heldLockSet.has_value()) { continue; }
|
if (!heldLockSet.has_value()) { continue; }
|
||||||
|
|
||||||
// Check if the firstFailedQutex is in this continuation's LockSet
|
// A miss is expected here; only a hit indicates a potential deadlock.
|
||||||
try {
|
auto lockUsageDesc = heldLockSet->get().findLockUsageDesc(
|
||||||
heldLockSet->get().getLockUsageDesc(firstFailedQutex);
|
firstFailedQutex);
|
||||||
} catch (const std::runtime_error& e) {
|
if (!lockUsageDesc.has_value()
|
||||||
std::cerr << __func__ << ": " << e.what() << std::endl;
|
|| lockUsageDesc->get().hasBeenReleased)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,10 +435,10 @@ SerializedAsynchronousContinuation<OriginalCbFnT>
|
|||||||
auto heldLockSet = currContin->getLockSet();
|
auto heldLockSet = currContin->getLockSet();
|
||||||
if (!heldLockSet.has_value()) { continue; }
|
if (!heldLockSet.has_value()) { continue; }
|
||||||
|
|
||||||
// Check if this continuation holds the foreign lock
|
// A miss is expected here; a hit indicates a potential gridlock.
|
||||||
try {
|
auto lockUsageDesc = heldLockSet->get().findLockUsageDesc(
|
||||||
const auto& lockUsageDesc = heldLockSet
|
foreignLock);
|
||||||
->get().getLockUsageDesc(foreignLock);
|
if (!lockUsageDesc.has_value()) { continue; }
|
||||||
|
|
||||||
// Matched! We hold a lock that the foreign owner is waiting for
|
// Matched! We hold a lock that the foreign owner is waiting for
|
||||||
std::cout << __func__ << ": Gridlock detected: We hold lock @"
|
std::cout << __func__ << ": Gridlock detected: We hold lock @"
|
||||||
@@ -449,10 +450,6 @@ SerializedAsynchronousContinuation<OriginalCbFnT>
|
|||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::runtime_error& e) {
|
|
||||||
// This continuation doesn't hold the foreign lock. Continue.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user