2022-06-22 - TSAN bug

while preparing release of latest LogATE version, i stumbled upon a bug in thread sanitizer. consider the following piece of code:

#include <thread>
#include <mutex>
#include <condition_variable>
int main()
  auto ready = false;
  std::mutex m;
  std::condition_variable cv;
  std::thread th{ [&]{
    // thread 1
    std::unique_lock<std::mutex> lock(m);
#if 0
    // OK!
    cv.wait( lock, [&]{ return ready; } );
#if 0
    // ERROR!
    cv.wait_until( lock, std::chrono::steady_clock::now() + std::chrono::minutes{1}, [&]{ return ready; } );
#if 1
    // ERROR!
    cv.wait_for( lock, std::chrono::minutes{1}, [&]{ return ready; } );
  } };
    // thread 2
    std::this_thread::sleep_for( std::chrono::seconds{1} );  // we should be wait()ing here
    std::lock_guard<std::mutex> lock{m};
    ready = true;

after compiling it with:

g++ -fsanitize=thread  -g3 -Wall -std=c++17 test.cpp -lpthread

we can see a very colorful output, indicating double-locking and race condition!

TSAN's report with warnings

the same issue is reported with both gcc and clang. so the problem is in the code, right? well… no. the clue that the problem is elsewhere is when you change which version of wait() is selected: regular one works fine, while time-constrained versions (i.e. deadline and timeout) report issues as below. changing C++ library does not change the output, but changing a compiler version does help.

here are the bugs i found already reported for this:

i've spent quite a bit of time today, trying to narrow down the issue and making it small and reproducible issue. then it turned out it's a know problem. life… ;)

the problem has been observed on UTs. even though here it was false-positive, running automated tests with sanitizers is a really great thing to do. if you still do not do it – i strongly encourage you to start doing so! :)

blog/2022/06/22/2022-06-22_-_tsan_bug.txt · Last modified: 2022/06/22 21:56 by basz
Back to top
Valid CSS Driven by DokuWiki Recent changes RSS feed Valid XHTML 1.0