google / sanitizers

AddressSanitizer, ThreadSanitizer, MemorySanitizer
Other
11.55k stars 1.04k forks source link

tsan: False positive for lock-order inversion due to two locks mapped to the same address. #1798

Open nanlour opened 2 months ago

nanlour commented 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
==================