@@ -62,6 +62,19 @@ void TestDoubleLock(bool should_throw)
62
62
g_debug_lockorder_abort = prev;
63
63
}
64
64
#endif /* DEBUG_LOCKORDER */
65
+
66
+ template <typename MutexType>
67
+ void TestInconsistentLockOrderDetected (MutexType& mutex1, MutexType& mutex2) NO_THREAD_SAFETY_ANALYSIS
68
+ {
69
+ ENTER_CRITICAL_SECTION (mutex1);
70
+ ENTER_CRITICAL_SECTION (mutex2);
71
+ #ifdef DEBUG_LOCKORDER
72
+ BOOST_CHECK_EXCEPTION (LEAVE_CRITICAL_SECTION (mutex1), std::logic_error, HasReason (" mutex1 was not most recent critical section locked" ));
73
+ #endif // DEBUG_LOCKORDER
74
+ LEAVE_CRITICAL_SECTION (mutex2);
75
+ LEAVE_CRITICAL_SECTION (mutex1);
76
+ BOOST_CHECK (LockStackEmpty ());
77
+ }
65
78
} // namespace
66
79
67
80
BOOST_FIXTURE_TEST_SUITE (sync_tests, BasicTestingSetup)
@@ -108,4 +121,28 @@ BOOST_AUTO_TEST_CASE(double_lock_recursive_mutex)
108
121
}
109
122
#endif /* DEBUG_LOCKORDER */
110
123
124
+ BOOST_AUTO_TEST_CASE (inconsistent_lock_order_detected)
125
+ {
126
+ #ifdef DEBUG_LOCKORDER
127
+ bool prev = g_debug_lockorder_abort;
128
+ g_debug_lockorder_abort = false ;
129
+ #endif // DEBUG_LOCKORDER
130
+
131
+ RecursiveMutex rmutex1, rmutex2;
132
+ TestInconsistentLockOrderDetected (rmutex1, rmutex2);
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 (rmutex1, rmutex2);
136
+
137
+ Mutex mutex1, mutex2;
138
+ TestInconsistentLockOrderDetected (mutex1, mutex2);
139
+ // By checking lock order consistency (CheckLastCritical) before any unlocking (LeaveCritical)
140
+ // the lock tracking data must not have been broken by exception.
141
+ TestInconsistentLockOrderDetected (mutex1, mutex2);
142
+
143
+ #ifdef DEBUG_LOCKORDER
144
+ g_debug_lockorder_abort = prev;
145
+ #endif // DEBUG_LOCKORDER
146
+ }
147
+
111
148
BOOST_AUTO_TEST_SUITE_END ()
0 commit comments