Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fake positive "WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock)" after mutex is unlock #57955

Open
Changqing-JING opened this issue Sep 24, 2022 · 0 comments
Labels
compiler-rt:tsan Thread sanitizer

Comments

@Changqing-JING
Copy link

Changqing-JING commented Sep 24, 2022

This bug is originally reported in google/sanitizer. But the original code is in llvm-project. So the ticket is referred to llvm for further analyzing and fix.

This bug is already reported by:
google/sanitizers#814
google/sanitizers#1419

To reproduce the bug:

Build and run the follow code with thread sanitizer.

#include <thread>
#include <mutex>
#include <atomic>

std::mutex m1;
std::mutex m2;
std::mutex m3;

std::atomic<int> counter {0};

void foo(){
  std::unique_lock<std::mutex> lock1(m1);
  std::unique_lock<std::mutex> lock2(m2);
}

void xoo(){
  foo();
  std::unique_lock<std::mutex> lock2(m2);
  std::unique_lock<std::mutex> lock3(m3);
}

void yoo(){
  std::unique_lock<std::mutex> lock3(m3);
  std::unique_lock<std::mutex> lock1(m1);
}

int main(){
  std::thread th1([]{
    while(true){
      xoo();
      if(counter>10){
        break;
      }
    }
  });

  std::thread th2([]{
    while(true){
      yoo();
      counter++;
      if(counter>10){
        break;
      }
    }
  });

  th1.join();
  th2.join();
}
mkdir build
clang++ -g -fsanitize=thread -o build/sanitizerDemo main.cpp
./build/sanitizerDemo

Expected behavior:

No warning and error

Observed behavior:

Get warning:

==================
WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock) (pid=2961)
  Cycle in lock order graph: M0 (0x55efb72306a8) => M1 (0x55efb72306d0) => M2 (0x55efb72306f8) => M0

  Mutex M1 acquired here while holding mutex M0 in thread T1:
    #0 pthread_mutex_lock <null> (sanitizerDemo+0x6cfaa) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #1 __gthread_mutex_lock(pthread_mutex_t*) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749:12 (sanitizerDemo+0xd0903) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #2 std::mutex::lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_mutex.h:100:17 (sanitizerDemo+0xd1715) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #3 std::unique_lock<std::mutex>::lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/unique_lock.h:139:17 (sanitizerDemo+0xd16a5) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #4 std::unique_lock<std::mutex>::unique_lock(std::mutex&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/unique_lock.h:69:2 (sanitizerDemo+0xd1457) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #5 foo() /home/jcq/workspace/ThreadSanitizerBugCandidate/main.cpp:13:32 (sanitizerDemo+0xd03d5) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #6 xoo() /home/jcq/workspace/ThreadSanitizerBugCandidate/main.cpp:17:3 (sanitizerDemo+0xd0465) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #7 main::$_0::operator()() const /home/jcq/workspace/ThreadSanitizerBugCandidate/main.cpp:30:7 (sanitizerDemo+0xd0de1) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #8 void std::__invoke_impl<void, main::$_0>(std::__invoke_other, main::$_0&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:61:14 (sanitizerDemo+0xd0d9d) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #9 std::__invoke_result<main::$_0>::type std::__invoke<main::$_0>(main::$_0&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:96:14 (sanitizerDemo+0xd0ced) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #10 void std::thread::_Invoker<std::tuple<main::$_0> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_thread.h:253:13 (sanitizerDemo+0xd0c95) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #11 std::thread::_Invoker<std::tuple<main::$_0> >::operator()() /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_thread.h:260:11 (sanitizerDemo+0xd0c35) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #12 std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::$_0> > >::_M_run() /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_thread.h:211:13 (sanitizerDemo+0xd0b49) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #13 <null> <null> (libstdc++.so.6+0xdc2c2) (BuildId: 725ef5da52ee6d881f9024d8238a989903932637)

    Hint: use TSAN_OPTIONS=second_deadlock_stack=1 to get more informative warning message

  Mutex M2 acquired here while holding mutex M1 in thread T1:
    #0 pthread_mutex_lock <null> (sanitizerDemo+0x6cfaa) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #1 __gthread_mutex_lock(pthread_mutex_t*) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749:12 (sanitizerDemo+0xd0903) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #2 std::mutex::lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_mutex.h:100:17 (sanitizerDemo+0xd1715) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #3 std::unique_lock<std::mutex>::lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/unique_lock.h:139:17 (sanitizerDemo+0xd16a5) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #4 std::unique_lock<std::mutex>::unique_lock(std::mutex&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/unique_lock.h:69:2 (sanitizerDemo+0xd1457) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #5 xoo() /home/jcq/workspace/ThreadSanitizerBugCandidate/main.cpp:19:32 (sanitizerDemo+0xd048f) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #6 main::$_0::operator()() const /home/jcq/workspace/ThreadSanitizerBugCandidate/main.cpp:30:7 (sanitizerDemo+0xd0de1) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #7 void std::__invoke_impl<void, main::$_0>(std::__invoke_other, main::$_0&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:61:14 (sanitizerDemo+0xd0d9d) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #8 std::__invoke_result<main::$_0>::type std::__invoke<main::$_0>(main::$_0&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:96:14 (sanitizerDemo+0xd0ced) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #9 void std::thread::_Invoker<std::tuple<main::$_0> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_thread.h:253:13 (sanitizerDemo+0xd0c95) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #10 std::thread::_Invoker<std::tuple<main::$_0> >::operator()() /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_thread.h:260:11 (sanitizerDemo+0xd0c35) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #11 std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::$_0> > >::_M_run() /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_thread.h:211:13 (sanitizerDemo+0xd0b49) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #12 <null> <null> (libstdc++.so.6+0xdc2c2) (BuildId: 725ef5da52ee6d881f9024d8238a989903932637)

  Mutex M0 acquired here while holding mutex M2 in thread T2:
    #0 pthread_mutex_lock <null> (sanitizerDemo+0x6cfaa) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #1 __gthread_mutex_lock(pthread_mutex_t*) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749:12 (sanitizerDemo+0xd0903) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #2 std::mutex::lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_mutex.h:100:17 (sanitizerDemo+0xd1715) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #3 std::unique_lock<std::mutex>::lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/unique_lock.h:139:17 (sanitizerDemo+0xd16a5) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #4 std::unique_lock<std::mutex>::unique_lock(std::mutex&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/unique_lock.h:69:2 (sanitizerDemo+0xd1457) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #5 yoo() /home/jcq/workspace/ThreadSanitizerBugCandidate/main.cpp:24:32 (sanitizerDemo+0xd0535) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #6 main::$_1::operator()() const /home/jcq/workspace/ThreadSanitizerBugCandidate/main.cpp:39:7 (sanitizerDemo+0xd1301) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #7 void std::__invoke_impl<void, main::$_1>(std::__invoke_other, main::$_1&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:61:14 (sanitizerDemo+0xd12bd) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #8 std::__invoke_result<main::$_1>::type std::__invoke<main::$_1>(main::$_1&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:96:14 (sanitizerDemo+0xd120d) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #9 void std::thread::_Invoker<std::tuple<main::$_1> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_thread.h:253:13 (sanitizerDemo+0xd11b5) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #10 std::thread::_Invoker<std::tuple<main::$_1> >::operator()() /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_thread.h:260:11 (sanitizerDemo+0xd1155) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #11 std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::$_1> > >::_M_run() /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_thread.h:211:13 (sanitizerDemo+0xd1069) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #12 <null> <null> (libstdc++.so.6+0xdc2c2) (BuildId: 725ef5da52ee6d881f9024d8238a989903932637)

  Thread T1 (tid=2963, running) created by main thread at:
    #0 pthread_create <null> (sanitizerDemo+0x4f41d) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xdc398) (BuildId: 725ef5da52ee6d881f9024d8238a989903932637)
    #2 main /home/jcq/workspace/ThreadSanitizerBugCandidate/main.cpp:28:15 (sanitizerDemo+0xd05cd) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)

  Thread T2 (tid=2964, running) created by main thread at:
    #0 pthread_create <null> (sanitizerDemo+0x4f41d) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xdc398) (BuildId: 725ef5da52ee6d881f9024d8238a989903932637)
    #2 main /home/jcq/workspace/ThreadSanitizerBugCandidate/main.cpp:37:15 (sanitizerDemo+0xd05df) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813)

SUMMARY: ThreadSanitizer: lock-order-inversion (potential deadlock) (/home/jcq/workspace/ThreadSanitizerBugCandidate/build/sanitizerDemo+0x6cfaa) (BuildId: c8889fc1fcd8a23e72c8e9304e3bd86a01df3813) in pthread_mutex_lock
==================
ThreadSanitizer: reported 1 warnings

Environment

Ubuntu 22.04 + clang-14(installed by apt)

$ uname -a
Linux ubuntu 5.15.0-25-generic #25-Ubuntu SMP Wed Mar 30 15:54:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

$ clang++ --version
Ubuntu clang version 14.0.0-1ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
@EugeneZelenko EugeneZelenko added compiler-rt:lsan Leak sanitizer compiler-rt:tsan Thread sanitizer and removed new issue compiler-rt:lsan Leak sanitizer labels Sep 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler-rt:tsan Thread sanitizer
Projects
None yet
Development

No branches or pull requests

2 participants