From 08cfe273ddf9bd7640456865926ec9d94b363520 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 12 Feb 2024 14:35:27 +0000 Subject: [PATCH 1/2] Release `LockData::dd_mutex` before calling `*_detected` functions Both `double_lock_detected()` and `potential_deadlock_detected()` functions call `LogPrintf()` which in turn implies locking of the `Logger::m_cs` mutex. To avoid a deadlock the latter must not have the `Mutex` type. With this change the mentioned restriction has been lifted, and it is possible now to use our regular `Mutex` type for the `Logger::m_cs` mutex instead of a dedicated `StdMutex` type. --- src/sync.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/sync.cpp b/src/sync.cpp index 58752a9f182..94cac4fa8a7 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -156,7 +156,7 @@ static void push_lock(MutexType* c, const CLockLocation& locklocation) std::is_base_of::value; LockData& lockdata = GetLockData(); - std::lock_guard lock(lockdata.dd_mutex); + std::unique_lock lock{lockdata.dd_mutex}; LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()]; lock_stack.emplace_back(c, locklocation); @@ -172,6 +172,7 @@ static void push_lock(MutexType* c, const CLockLocation& locklocation) // same thread as that results in an undefined behavior. auto lock_stack_copy = lock_stack; lock_stack.pop_back(); + lock.unlock(); double_lock_detected(c, lock_stack_copy); // double_lock_detected() does not return. } @@ -182,9 +183,11 @@ static void push_lock(MutexType* c, const CLockLocation& locklocation) const LockPair p2 = std::make_pair(c, i.first); if (lockdata.lockorders.count(p2)) { - auto lock_stack_copy = lock_stack; + auto lock_stack_current = lock_stack; lock_stack.pop_back(); - potential_deadlock_detected(p1, lockdata.lockorders[p2], lock_stack_copy); + auto lock_stack_previous = lockdata.lockorders[p2]; + lock.unlock(); + potential_deadlock_detected(p1, lock_stack_previous, lock_stack_current); // potential_deadlock_detected() does not return. } From 38f93fe0cb680425f5fec7c794b39c0e1795f9dc Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 12 Feb 2024 14:35:35 +0000 Subject: [PATCH 2/2] refactor: Add `[[noreturn]]` attribute to `*_detected()` functions --- src/sync.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sync.cpp b/src/sync.cpp index 94cac4fa8a7..0bb335dc8f7 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -92,7 +92,7 @@ LockData& GetLockData() { return lock_data; } -static void potential_deadlock_detected(const LockPair& mismatch, const LockStack& s1, const LockStack& s2) +[[noreturn]] static void potential_deadlock_detected(const LockPair& mismatch, const LockStack& s1, const LockStack& s2) { LogPrintf("POTENTIAL DEADLOCK DETECTED\n"); LogPrintf("Previous lock order was:\n"); @@ -128,7 +128,7 @@ static void potential_deadlock_detected(const LockPair& mismatch, const LockStac throw std::logic_error(strprintf("potential deadlock detected: %s -> %s -> %s", mutex_b, mutex_a, mutex_b)); } -static void double_lock_detected(const void* mutex, const LockStack& lock_stack) +[[noreturn]] static void double_lock_detected(const void* mutex, const LockStack& lock_stack) { LogPrintf("DOUBLE LOCK DETECTED\n"); LogPrintf("Lock order:\n");