Bitcoin Core
31.1.0
P2P Digital Currency
Toggle main menu visibility
Loading...
Searching...
No Matches
src
test
sync_tests.cpp
Go to the documentation of this file.
1
// Copyright (c) 2012-present 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/util/common.h
>
7
8
#include <boost/test/unit_test.hpp>
9
10
#include <mutex>
11
#include <stdexcept>
12
13
namespace
{
14
template
<
typename
MutexType>
15
void
TestPotentialDeadLockDetected(MutexType& mutex1, MutexType& mutex2)
16
{
17
{
18
LOCK2
(mutex1, mutex2);
19
}
20
BOOST_CHECK
(
LockStackEmpty
());
21
bool
error_thrown =
false
;
22
try
{
23
LOCK2
(mutex2, mutex1);
24
}
catch
(
const
std::logic_error& e) {
25
BOOST_CHECK_EQUAL
(e.what(),
"potential deadlock detected: mutex1 -> mutex2 -> mutex1"
);
26
error_thrown =
true
;
27
}
28
BOOST_CHECK
(
LockStackEmpty
());
29
#ifdef DEBUG_LOCKORDER
30
BOOST_CHECK
(error_thrown);
31
#else
32
BOOST_CHECK
(!error_thrown);
33
#endif
34
}
35
36
#ifdef DEBUG_LOCKORDER
37
template
<
typename
MutexType>
38
void
TestDoubleLock2(MutexType&
m
)
39
{
40
LOCK
(
m
);
41
}
42
43
template
<
typename
MutexType>
44
void
TestDoubleLock(
bool
should_throw)
45
{
46
const
bool
prev = g_debug_lockorder_abort;
47
g_debug_lockorder_abort =
false
;
48
49
MutexType
m
;
50
{
51
LOCK
(
m
);
52
if
(should_throw) {
53
BOOST_CHECK_EXCEPTION(TestDoubleLock2(
m
), std::logic_error,
54
HasReason
(
"double lock detected"
));
55
}
else
{
56
BOOST_CHECK_NO_THROW
(TestDoubleLock2(
m
));
57
}
58
}
59
BOOST_CHECK
(
LockStackEmpty
());
60
61
g_debug_lockorder_abort = prev;
62
}
63
#endif
/* DEBUG_LOCKORDER */
64
65
template
<
typename
MutexType>
66
void
TestInconsistentLockOrderDetected(MutexType& mutex1, MutexType& mutex2)
67
{
68
{
69
WAIT_LOCK
(mutex1, lock1);
70
LOCK
(mutex2);
71
#ifdef DEBUG_LOCKORDER
72
BOOST_CHECK_EXCEPTION(
REVERSE_LOCK
(lock1, mutex1), std::logic_error,
HasReason
(
"mutex1 was not most recent critical section locked"
));
73
#endif
// DEBUG_LOCKORDER
74
}
75
BOOST_CHECK
(
LockStackEmpty
());
76
}
77
}
// namespace
78
79
BOOST_AUTO_TEST_SUITE(sync_tests)
80
81
BOOST_AUTO_TEST_CASE
(potential_deadlock_detected)
82
{
83
#ifdef DEBUG_LOCKORDER
84
bool
prev = g_debug_lockorder_abort;
85
g_debug_lockorder_abort =
false
;
86
#endif
87
88
RecursiveMutex
rmutex1, rmutex2;
89
TestPotentialDeadLockDetected(rmutex1, rmutex2);
90
// The second test ensures that lock tracking data have not been broken by exception.
91
TestPotentialDeadLockDetected(rmutex1, rmutex2);
92
93
Mutex
mutex1, mutex2;
94
TestPotentialDeadLockDetected(mutex1, mutex2);
95
// The second test ensures that lock tracking data have not been broken by exception.
96
TestPotentialDeadLockDetected(mutex1, mutex2);
97
98
#ifdef DEBUG_LOCKORDER
99
g_debug_lockorder_abort = prev;
100
#endif
101
}
102
103
/* Double lock would produce an undefined behavior. Thus, we only do that if
104
* DEBUG_LOCKORDER is activated to detect it. We don't want non-DEBUG_LOCKORDER
105
* build to produce tests that exhibit known undefined behavior. */
106
#ifdef DEBUG_LOCKORDER
107
BOOST_AUTO_TEST_CASE
(double_lock_mutex)
108
{
109
TestDoubleLock<Mutex>(
/*should_throw=*/
true
);
110
}
111
112
BOOST_AUTO_TEST_CASE
(double_lock_recursive_mutex)
113
{
114
TestDoubleLock<RecursiveMutex>(
/*should_throw=*/
false
);
115
}
116
#endif
/* DEBUG_LOCKORDER */
117
118
BOOST_AUTO_TEST_CASE
(inconsistent_lock_order_detected)
119
{
120
#ifdef DEBUG_LOCKORDER
121
bool
prev = g_debug_lockorder_abort;
122
g_debug_lockorder_abort =
false
;
123
#endif
// DEBUG_LOCKORDER
124
125
RecursiveMutex
rmutex1, rmutex2;
126
TestInconsistentLockOrderDetected(rmutex1, rmutex2);
127
// By checking lock order consistency (CheckLastCritical) before any unlocking (LeaveCritical)
128
// the lock tracking data must not have been broken by exception.
129
TestInconsistentLockOrderDetected(rmutex1, rmutex2);
130
131
Mutex
mutex1, mutex2;
132
TestInconsistentLockOrderDetected(mutex1, mutex2);
133
// By checking lock order consistency (CheckLastCritical) before any unlocking (LeaveCritical)
134
// the lock tracking data must not have been broken by exception.
135
TestInconsistentLockOrderDetected(mutex1, mutex2);
136
137
#ifdef DEBUG_LOCKORDER
138
g_debug_lockorder_abort = prev;
139
#endif
// DEBUG_LOCKORDER
140
}
141
142
BOOST_AUTO_TEST_SUITE_END
()
HasReason
BOOST_CHECK_EXCEPTION predicates to check the specific validation error.
Definition
common.h:18
BOOST_AUTO_TEST_SUITE_END
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(ipc_tests)
Definition
ipc_tests.cpp:13
BOOST_CHECK_EQUAL
#define BOOST_CHECK_EQUAL(v1, v2)
Definition
object.cpp:17
BOOST_CHECK_NO_THROW
#define BOOST_CHECK_NO_THROW(stmt)
Definition
object.cpp:27
BOOST_CHECK
#define BOOST_CHECK(expr)
Definition
object.cpp:16
ByteUnit::m
@ m
Definition
strencodings.h:48
sync.h
WAIT_LOCK
#define WAIT_LOCK(cs, name)
Definition
sync.h:264
Mutex
AnnotatedMixin< std::mutex > Mutex
Wrapped mutex: supports waiting but not recursive locking.
Definition
sync.h:123
LOCK2
#define LOCK2(cs1, cs2)
Definition
sync.h:259
RecursiveMutex
AnnotatedMixin< std::recursive_mutex > RecursiveMutex
Wrapped mutex: supports recursive locking, but no waiting TODO: We should move away from using the re...
Definition
sync.h:120
REVERSE_LOCK
#define REVERSE_LOCK(g, cs)
Definition
sync.h:244
LOCK
#define LOCK(cs)
Definition
sync.h:258
LockStackEmpty
bool LockStackEmpty()
Definition
sync.h:77
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(potential_deadlock_detected)
Definition
sync_tests.cpp:81
common.h
Generated on
for Bitcoin Core by
1.17.0