17#include <system_error>
20#include <unordered_map>
49 std::string Name()
const {
return mutexName; }
60using LockStack = std::vector<LockStackItem>;
61using LockStacks = std::unordered_map<std::thread::id, LockStack>;
63using LockPair = std::pair<void *, void *>;
64using LockOrders = std::map<LockPair, LockStack>;
87 LogPrintf(
"POTENTIAL DEADLOCK DETECTED\n");
115 "Assertion failed: detected inconsistent lock order for %s, "
116 "details in debug log.\n",
117 s2.back().second.ToString());
120 throw std::logic_error(
130 if (i.first == mutex) {
137 "Assertion failed: detected double lock for %s, details in "
142 throw std::logic_error(
"double lock detected");
145template <
typename MutexType>
148 std::is_base_of<RecursiveMutex, MutexType>::value ||
149 std::is_base_of<std::recursive_mutex, MutexType>::value;
152 std::lock_guard<std::mutex> lock(
lockdata.dd_mutex);
194 std::lock_guard<std::mutex> lock(
lockdata.dd_mutex);
199 lockdata.m_lock_stacks.erase(std::this_thread::get_id());
203template <
typename MutexType>
212template void EnterCritical(
const char *,
const char *,
int, std::mutex *,
215 std::recursive_mutex *,
bool);
218 const char *file,
int line) {
220 std::lock_guard<std::mutex> lock(
lockdata.dd_mutex);
223 lockdata.m_lock_stacks[std::this_thread::get_id()];
232 LogPrintf(
"INCONSISTENT LOCK ORDER DETECTED\n");
233 LogPrintf(
"Current lock order (least recent first) is:\n");
239 "%s:%s %s was not most recent critical section locked, "
240 "details in debug log.\n",
244 throw std::logic_error(
254 std::lock_guard<std::mutex> lock(
lockdata.dd_mutex);
257 lockdata.m_lock_stacks[std::this_thread::get_id()];
260 result += i.second.ToString() + std::string(
"\n");
267 std::lock_guard<std::mutex> lock(
lockdata.dd_mutex);
270 lockdata.m_lock_stacks[std::this_thread::get_id()];
272 if (i.first == mutex) {
280template <
typename MutexType>
287 "Assertion failed: lock %s not held in %s:%i; locks held:\n%s",
295template <
typename MutexType>
302 "Assertion failed: lock %s held in %s:%i; locks held:\n%s",
313 std::lock_guard<std::mutex> lock(
lockdata.dd_mutex);
314 const LockPair item = std::make_pair(
cs,
nullptr);
315 LockOrders::iterator it =
lockdata.lockorders.lower_bound(item);
316 while (it !=
lockdata.lockorders.end() && it->first.first ==
cs) {
318 std::make_pair(it->first.second, it->first.first);
322 InvLockOrders::iterator
invit =
lockdata.invlockorders.lower_bound(item);
332 std::lock_guard<std::mutex> lock(
lockdata.dd_mutex);
333 const auto it =
lockdata.m_lock_stacks.find(std::this_thread::get_id());
334 if (it ==
lockdata.m_lock_stacks.end()) {
337 return it->second.empty();
#define LogPrintfToBeContinued
These are aliases used to explicitly state that the message should not end with a newline character.
const std::string & ThreadGetInternalName()
Get the thread's internal (in-memory) name; used e.g.
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
static std::string ToString(const CService &ip)
void AssertLockHeldInternal(const char *pszName, const char *pszFile, int nLine, MutexType *cs) EXCLUSIVE_LOCKS_REQUIRED(cs)
void EnterCritical(const char *pszName, const char *pszFile, int nLine, MutexType *cs, bool fTry=false)
void DeleteLock(void *cs)
void CheckLastCritical(void *cs, std::string &lockname, const char *guardname, const char *file, int line)
void AssertLockNotHeldInternal(const char *pszName, const char *pszFile, int nLine, MutexType *cs) LOCKS_EXCLUDED(cs)