aboutsummaryrefslogtreecommitdiff
path: root/src/sync.cpp
diff options
context:
space:
mode:
authorMarcoFalke <falke.marco@gmail.com>2020-08-04 17:00:08 +0200
committerMarcoFalke <falke.marco@gmail.com>2020-08-04 17:00:15 +0200
commit0f16212c5931b30f430014caa485de53f9a14920 (patch)
treee45f8e64223c529d01b226d4560771a27fadb71d /src/sync.cpp
parent3c93623be20d534bb653410db03d38152135e2e6 (diff)
parent63e9e40b73507b0c9361fc8728d4e97fd72c9ec9 (diff)
downloadbitcoin-0f16212c5931b30f430014caa485de53f9a14920.tar.xz
Merge #19340: Preserve the `LockData` initial state if "potential deadlock detected" exception thrown
63e9e40b73507b0c9361fc8728d4e97fd72c9ec9 test: Add LockStackEmpty() (Hennadii Stepanov) 42b2a953735457cbf7b62a18b89811a66e573298 test: Repeat deadlock tests (Hennadii Stepanov) 1f96be25b020a56afa330286ee4f241aa14d3983 Preserve initial state if push_lock() throws exception (Hennadii Stepanov) Pull request description: On master (e3fa3c7d671e34038a262bb2db16b30bee82153d) if the `push_lock()` throws the "potential deadlock detected" exception (via the `potential_deadlock_detected()` call), the `LockData` instance internal state differs from one when the `push_lock()` was called. This non-well behaviour makes (at least) testing brittle. This PR preserves the `LockData` instance initial state if `push_lock()` throws an exception, and improves the `sync_tests` unit test. ACKs for top commit: MarcoFalke: re-ACK 63e9e40b73 vasild: ACK 63e9e40 Tree-SHA512: 7679182154ce5f079b44b790faf76eb5f553328dea70a326ff6b600db70e2f9ae015a33a104ca070cb660318280cb79b6b42e37ea5166f26f9e627ba721fcdec
Diffstat (limited to 'src/sync.cpp')
-rw-r--r--src/sync.cpp22
1 files changed, 19 insertions, 3 deletions
diff --git a/src/sync.cpp b/src/sync.cpp
index 10f0483189..4be13a3c48 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -149,12 +149,17 @@ static void push_lock(void* c, const CLockLocation& locklocation)
const LockPair p1 = std::make_pair(i.first, c);
if (lockdata.lockorders.count(p1))
continue;
- lockdata.lockorders.emplace(p1, lock_stack);
const LockPair p2 = std::make_pair(c, i.first);
+ if (lockdata.lockorders.count(p2)) {
+ auto lock_stack_copy = lock_stack;
+ lock_stack.pop_back();
+ potential_deadlock_detected(p1, lockdata.lockorders[p2], lock_stack_copy);
+ // potential_deadlock_detected() does not return.
+ }
+
+ lockdata.lockorders.emplace(p1, lock_stack);
lockdata.invlockorders.insert(p2);
- if (lockdata.lockorders.count(p2))
- potential_deadlock_detected(p1, lockdata.lockorders[p2], lockdata.lockorders[p1]);
}
}
@@ -259,6 +264,17 @@ void DeleteLock(void* cs)
}
}
+bool LockStackEmpty()
+{
+ LockData& lockdata = GetLockData();
+ std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
+ const auto it = lockdata.m_lock_stacks.find(std::this_thread::get_id());
+ if (it == lockdata.m_lock_stacks.end()) {
+ return true;
+ }
+ return it->second.empty();
+}
+
bool g_debug_lockorder_abort = true;
#endif /* DEBUG_LOCKORDER */