Skip to content

Commit 41b88e9

Browse files
committed
Add unit test for DEBUG_LOCKORDER code
1 parent 2b67354 commit 41b88e9

File tree

4 files changed

+56
-1
lines changed

4 files changed

+56
-1
lines changed

src/Makefile.test.include

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ BITCOIN_TESTS =\
8181
test/sigopcount_tests.cpp \
8282
test/skiplist_tests.cpp \
8383
test/streams_tests.cpp \
84+
test/sync_tests.cpp \
8485
test/timedata_tests.cpp \
8586
test/torcontrol_tests.cpp \
8687
test/transaction_tests.cpp \

src/sync.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,11 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch,
100100
}
101101
LogPrintf(" %s\n", i.second.ToString());
102102
}
103-
assert(false);
103+
if (g_debug_lockorder_abort) {
104+
fprintf(stderr, "Assertion failed: detected inconsistent lock order at %s:%i, details in debug log.\n", __FILE__, __LINE__);
105+
abort();
106+
}
107+
throw std::logic_error("potential deadlock detected");
104108
}
105109

106110
static void push_lock(void* c, const CLockLocation& locklocation)
@@ -189,4 +193,6 @@ void DeleteLock(void* cs)
189193
}
190194
}
191195

196+
bool g_debug_lockorder_abort = true;
197+
192198
#endif /* DEBUG_LOCKORDER */

src/sync.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ std::string LocksHeld();
7777
void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) ASSERT_EXCLUSIVE_LOCK(cs);
7878
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs);
7979
void DeleteLock(void* cs);
80+
81+
/**
82+
* Call abort() if a potential lock order deadlock bug is detected, instead of
83+
* just logging information and throwing a logic_error. Defaults to true, and
84+
* set to false in DEBUG_LOCKORDER unit tests.
85+
*/
86+
extern bool g_debug_lockorder_abort;
8087
#else
8188
void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
8289
void static inline LeaveCritical() {}

src/test/sync_tests.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) 2012-2017 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <sync.h>
6+
#include <test/test_bitcoin.h>
7+
8+
#include <boost/test/unit_test.hpp>
9+
10+
BOOST_FIXTURE_TEST_SUITE(sync_tests, BasicTestingSetup)
11+
12+
BOOST_AUTO_TEST_CASE(potential_deadlock_detected)
13+
{
14+
#ifdef DEBUG_LOCKORDER
15+
bool prev = g_debug_lockorder_abort;
16+
g_debug_lockorder_abort = false;
17+
#endif
18+
19+
CCriticalSection mutex1, mutex2;
20+
{
21+
LOCK2(mutex1, mutex2);
22+
}
23+
bool error_thrown = false;
24+
try {
25+
LOCK2(mutex2, mutex1);
26+
} catch (const std::logic_error& e) {
27+
BOOST_CHECK_EQUAL(e.what(), "potential deadlock detected");
28+
error_thrown = true;
29+
}
30+
#ifdef DEBUG_LOCKORDER
31+
BOOST_CHECK(error_thrown);
32+
#else
33+
BOOST_CHECK(!error_thrown);
34+
#endif
35+
36+
#ifdef DEBUG_LOCKORDER
37+
g_debug_lockorder_abort = prev;
38+
#endif
39+
}
40+
41+
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)