sync: Improve CheckLastCritical()

This commit adds actual lock stack logging if check fails.
This commit is contained in:
Hennadii Stepanov 2020-09-20 11:33:48 +03:00
parent da957cd62e
commit c5e3e74f70
No known key found for this signature in database
GPG key ID: 410108112E7EA81F
2 changed files with 25 additions and 15 deletions

View file

@ -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) void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line)
{ {
{ LockData& lockdata = GetLockData();
LockData& lockdata = GetLockData(); std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
const LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()]; const LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()];
if (!lock_stack.empty()) { if (!lock_stack.empty()) {
const auto& lastlock = lock_stack.back(); const auto& lastlock = lock_stack.back();
if (lastlock.first == cs) { if (lastlock.first == cs) {
lockname = lastlock.second.Name(); lockname = lastlock.second.Name();
return; 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() void LeaveCritical()

View file

@ -48,12 +48,14 @@ BOOST_AUTO_TEST_CASE(reverselock_errors)
WAIT_LOCK(mutex, lock); WAIT_LOCK(mutex, lock);
#ifdef DEBUG_LOCKORDER #ifdef DEBUG_LOCKORDER
bool prev = g_debug_lockorder_abort;
g_debug_lockorder_abort = false;
// Make sure trying to reverse lock a previous lock fails // Make sure trying to reverse lock a previous lock fails
try { BOOST_CHECK_EXCEPTION(REVERSE_LOCK(lock2), std::logic_error, HasReason("lock2 was not most recent critical section locked"));
REVERSE_LOCK(lock2);
BOOST_CHECK(false); // REVERSE_LOCK(lock2) succeeded
} catch(...) { }
BOOST_CHECK(lock2.owns_lock()); BOOST_CHECK(lock2.owns_lock());
g_debug_lockorder_abort = prev;
#endif #endif
// Make sure trying to reverse lock an unlocked lock fails // Make sure trying to reverse lock an unlocked lock fails