Open nanlour opened 2 months ago
It seems that if two locks are mapped to the same address, the sanitizer considers them as the same lock. Here is an example code that triggers this warning:
#include <mutex> std::mutex m1; void foo(bool ok) { std::mutex m2; std::unique_lock l1(m1, std::defer_lock); if(!ok) l1.lock(); std::unique_lock l2(m2); if (ok) l1.lock(); } int main() { foo(false); foo(true); return 0; }
Building and running it produces the following output:
================== WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock) (pid=81574) Cycle in lock order graph: M0 (0x560a6196cae8) => M1 (0x7ffef6323e90) => M0 Mutex M1 acquired here while holding mutex M0 in main thread: #0 pthread_mutex_lock <null> (main+0x6227e) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #1 __gthread_mutex_lock(pthread_mutex_t*) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14/bits/gthr-default.h:762:14 (main+0xe0df3) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #2 std::mutex::lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_mutex.h:113:17 (main+0xe1275) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #3 std::unique_lock<std::mutex>::lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/unique_lock.h:147:17 (main+0xe0f55) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #4 std::unique_lock<std::mutex>::unique_lock(std::mutex&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/unique_lock.h:73:2 (main+0xe0ffe) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #5 foo(bool) /threadSemtizer/main.cpp:9:22 (main+0xe0c65) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #6 main /threadSemtizer/main.cpp:15:5 (main+0xe0d0e) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) Mutex M0 previously acquired by the same thread here: #0 pthread_mutex_lock <null> (main+0x6227e) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #1 __gthread_mutex_lock(pthread_mutex_t*) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14/bits/gthr-default.h:762:14 (main+0xe0df3) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #2 std::mutex::lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_mutex.h:113:17 (main+0xe1275) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #3 std::unique_lock<std::mutex>::lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/unique_lock.h:147:17 (main+0xe0f55) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #4 foo(bool) /threadSemtizer/main.cpp:8:16 (main+0xe0c3d) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #5 main /threadSemtizer/main.cpp:15:5 (main+0xe0d0e) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) Mutex M0 acquired here while holding mutex M1 in main thread: #0 pthread_mutex_lock <null> (main+0x6227e) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #1 __gthread_mutex_lock(pthread_mutex_t*) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14/bits/gthr-default.h:762:14 (main+0xe0df3) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #2 std::mutex::lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_mutex.h:113:17 (main+0xe1275) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #3 std::unique_lock<std::mutex>::lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/unique_lock.h:147:17 (main+0xe0f55) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #4 foo(bool) /threadSemtizer/main.cpp:10:16 (main+0xe0c7d) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #5 main /threadSemtizer/main.cpp:16:5 (main+0xe0d1d) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) Mutex M1 previously acquired by the same thread here: #0 pthread_mutex_lock <null> (main+0x6227e) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #1 __gthread_mutex_lock(pthread_mutex_t*) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14/bits/gthr-default.h:762:14 (main+0xe0df3) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #2 std::mutex::lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_mutex.h:113:17 (main+0xe1275) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #3 std::unique_lock<std::mutex>::lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/unique_lock.h:147:17 (main+0xe0f55) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #4 std::unique_lock<std::mutex>::unique_lock(std::mutex&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/unique_lock.h:73:2 (main+0xe0ffe) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #5 foo(bool) /threadSemtizer/main.cpp:9:22 (main+0xe0c65) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) #6 main /threadSemtizer/main.cpp:16:5 (main+0xe0d1d) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) SUMMARY: ThreadSanitizer: lock-order-inversion (potential deadlock) (/threadSemtizer/main+0x6227e) (BuildId: aab00fd10cf0f00c10ca928364603028f30e183a) in pthread_mutex_lock ==================
It seems that if two locks are mapped to the same address, the sanitizer considers them as the same lock. Here is an example code that triggers this warning:
Building and running it produces the following output: