aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHennadii Stepanov <32963518+hebasto@users.noreply.github.com>2020-09-20 11:33:48 +0300
committerHennadii Stepanov <32963518+hebasto@users.noreply.github.com>2020-12-10 20:46:29 +0200
commitc5e3e74f70c29ac8852903ef425f5f327d5da969 (patch)
tree4c5dacce17a448d00e01a248d36ef03ce78642b9
parentda957cd62ecc7fde5fa1dfcd134a73b388c2d438 (diff)
sync: Improve CheckLastCritical()
This commit adds actual lock stack logging if check fails.
-rw-r--r--src/sync.cpp32
-rw-r--r--src/test/reverselock_tests.cpp10
2 files changed, 26 insertions, 16 deletions
diff --git a/src/sync.cpp b/src/sync.cpp
index f07916041a..acfbe8fe29 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -228,20 +228,28 @@ template void EnterCritical(const char*, const char*, int, boost::mutex*, bool);
void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line)
{
- {
- LockData& lockdata = GetLockData();
- std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
-
- const LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()];
- if (!lock_stack.empty()) {
- const auto& lastlock = lock_stack.back();
- if (lastlock.first == cs) {
- lockname = lastlock.second.Name();
- return;
- }
+ LockData& lockdata = GetLockData();
+ std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
+
+ const LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()];
+ if (!lock_stack.empty()) {
+ const auto& lastlock = lock_stack.back();
+ if (lastlock.first == cs) {
+ lockname = lastlock.second.Name();
+ return;
}
}
- throw std::system_error(EPERM, std::generic_category(), strprintf("%s:%s %s was not most recent critical section locked", file, line, guardname));
+
+ LogPrintf("INCONSISTENT LOCK ORDER DETECTED\n");
+ LogPrintf("Current lock order (least recent first) is:\n");
+ for (const LockStackItem& i : lock_stack) {
+ LogPrintf(" %s\n", i.second.ToString());
+ }
+ if (g_debug_lockorder_abort) {
+ tfm::format(std::cerr, "%s:%s %s was not most recent critical section locked, details in debug log.\n", file, line, guardname);
+ abort();
+ }
+ throw std::logic_error(strprintf("%s was not most recent critical section locked", guardname));
}
void LeaveCritical()
diff --git a/src/test/reverselock_tests.cpp b/src/test/reverselock_tests.cpp
index a42608a66d..7da364d316 100644
--- a/src/test/reverselock_tests.cpp
+++ b/src/test/reverselock_tests.cpp
@@ -48,12 +48,14 @@ BOOST_AUTO_TEST_CASE(reverselock_errors)
WAIT_LOCK(mutex, lock);
#ifdef DEBUG_LOCKORDER
+ bool prev = g_debug_lockorder_abort;
+ g_debug_lockorder_abort = false;
+
// Make sure trying to reverse lock a previous lock fails
- try {
- REVERSE_LOCK(lock2);
- BOOST_CHECK(false); // REVERSE_LOCK(lock2) succeeded
- } catch(...) { }
+ BOOST_CHECK_EXCEPTION(REVERSE_LOCK(lock2), std::logic_error, HasReason("lock2 was not most recent critical section locked"));
BOOST_CHECK(lock2.owns_lock());
+
+ g_debug_lockorder_abort = prev;
#endif
// Make sure trying to reverse lock an unlocked lock fails