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

@ -227,7 +227,6 @@ template void EnterCritical(const char*, const char*, int, std::recursive_mutex*
template void EnterCritical(const char*, const char*, int, boost::mutex*, bool); 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);
@ -240,8 +239,17 @@ void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, c
return; return;
} }
} }
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());
} }
throw std::system_error(EPERM, std::generic_category(), strprintf("%s:%s %s was not most recent critical section locked", file, line, guardname)); 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