<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/142370>142370</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            TSan seems to ignore std::shared_timed_mutex
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          mhier
      </td>
    </tr>
</table>

<pre>
    The ThreadSanitizer seems to ignore `std::shared_timed_mutex`es which have been locked via `try_lock_for()` and consequently reports false-positive data races.

Here is a minimal but complete code example:

```C++
#include <unistd.h>

#include <iostream>
#include <shared_mutex>
#include <thread>

int main([[maybe_unused]] int argc, [[maybe_unused]] char** argv) {
 std::shared_timed_mutex mx;

  int x = 0;

  auto t0 = std::thread([&] {
    for(size_t i = 0; i < 10; ++i) {
      usleep(100000);
      auto ok = mx.try_lock_for(std::chrono::seconds(600));
      if(!ok) {
        throw std::logic_error("No lock!");
      }
      x++;
      mx.unlock();
 }
  });

  for(size_t i = 0; i < 10; ++i) {
    usleep(100000);
    auto ok = mx.try_lock_for(std::chrono::seconds(600));
    if(!ok) {
      throw std::logic_error("No lock!");
    }
    std::cout << x << std::endl;
 mx.unlock();
  }

  t0.join();
}
```

Compiling this code with TSan enabled and running it will produce the following output:

```
0
/usr/bin/llvm-symbolizer-18: error: '[stack]': No such file or directory
==================
WARNING: ThreadSanitizer: data race (pid=511614)
  Write of size 4 at 0x7fffffffce8c by thread T1:
    #0 main::$_0::operator()() const /home/mhier/software/sources/CppPlayground/src/main.cc:19:8 (CppPlayground+0xe006b) (BuildId: dc419eb81c4ef89babd371b15b4ef9c1a4f8715b)
 #1 void std::__invoke_impl<void, main::$_0>(std::__invoke_other, main::$_0&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/invoke.h:61:14 (CppPlayground+0xdffb5) (BuildId: dc419eb81c4ef89babd371b15b4ef9c1a4f8715b)
 #2 std::__invoke_result<main::$_0>::type std::__invoke<main::$_0>(main::$_0&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/invoke.h:96:14 (CppPlayground+0xdff85) (BuildId: dc419eb81c4ef89babd371b15b4ef9c1a4f8715b)
 #3 void std::thread::_Invoker<std::tuple<main::$_0>>::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/std_thread.h:292:13 (CppPlayground+0xdff55) (BuildId: dc419eb81c4ef89babd371b15b4ef9c1a4f8715b)
 #4 std::thread::_Invoker<std::tuple<main::$_0>>::operator()() /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/std_thread.h:299:11 (CppPlayground+0xdff25) (BuildId: dc419eb81c4ef89babd371b15b4ef9c1a4f8715b)
 #5 std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::$_0>>>::_M_run() /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/std_thread.h:244:13 (CppPlayground+0xdfe49) (BuildId: dc419eb81c4ef89babd371b15b4ef9c1a4f8715b)
 #6 execute_native_thread_routine /build/gcc-14-ig5ci0/gcc-14-14.2.0/build/x86_64-linux-gnu/libstdc++-v3/src/c++11/../../../../../src/libstdc++-v3/src/c++11/thread.cc:104:18 (libstdc++.so.6+0xecdb3) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)

  Previous read of size 4 at 0x7fffffffce8c by main thread:
    #0 main /home/mhier/software/sources/CppPlayground/src/main.cc:30:18 (CppPlayground+0xdfbfd) (BuildId: dc419eb81c4ef89babd371b15b4ef9c1a4f8715b)

  As if synchronized via sleep:
    #0 usleep <null> (CppPlayground+0x5dbca) (BuildId: dc419eb81c4ef89babd371b15b4ef9c1a4f8715b)
    #1 main::$_0::operator()() const /home/mhier/software/sources/CppPlayground/src/main.cc:14:7 (CppPlayground+0xe0019) (BuildId: dc419eb81c4ef89babd371b15b4ef9c1a4f8715b)
 #2 void std::__invoke_impl<void, main::$_0>(std::__invoke_other, main::$_0&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/invoke.h:61:14 (CppPlayground+0xdffb5) (BuildId: dc419eb81c4ef89babd371b15b4ef9c1a4f8715b)
 #3 std::__invoke_result<main::$_0>::type std::__invoke<main::$_0>(main::$_0&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/invoke.h:96:14 (CppPlayground+0xdff85) (BuildId: dc419eb81c4ef89babd371b15b4ef9c1a4f8715b)
 #4 void std::thread::_Invoker<std::tuple<main::$_0>>::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/std_thread.h:292:13 (CppPlayground+0xdff55) (BuildId: dc419eb81c4ef89babd371b15b4ef9c1a4f8715b)
 #5 std::thread::_Invoker<std::tuple<main::$_0>>::operator()() /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/std_thread.h:299:11 (CppPlayground+0xdff25) (BuildId: dc419eb81c4ef89babd371b15b4ef9c1a4f8715b)
 #6 std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::$_0>>>::_M_run() /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/std_thread.h:244:13 (CppPlayground+0xdfe49) (BuildId: dc419eb81c4ef89babd371b15b4ef9c1a4f8715b)
 #7 execute_native_thread_routine /build/gcc-14-ig5ci0/gcc-14-14.2.0/build/x86_64-linux-gnu/libstdc++-v3/src/c++11/../../../../../src/libstdc++-v3/src/c++11/thread.cc:104:18 (libstdc++.so.6+0xecdb3) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)

  Location is stack of main thread.

  Location is global '??' at 0x7ffffffdd000 ([stack]+0x1fe8c)

 Thread T1 (tid=511616, running) created by main thread at:
    #0 pthread_create <null> (CppPlayground+0x6083b) (BuildId: dc419eb81c4ef89babd371b15b4ef9c1a4f8715b)
    #1 __gthread_create /build/gcc-14-ig5ci0/gcc-14-14.2.0/build/x86_64-linux-gnu/libstdc++-v3/include/x86_64-linux-gnu/bits/gthr-default.h:676:35 (libstdc++.so.6+0xeceb0) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State>>, void (*)()) /build/gcc-14-ig5ci0/gcc-14-14.2.0/build/x86_64-linux-gnu/libstdc++-v3/src/c++11/../../../../../src/libstdc++-v3/src/c++11/thread.cc:172:37 (libstdc++.so.6+0xeceb0)
    #3 main /home/mhier/software/sources/CppPlayground/src/main.cc:12:13 (CppPlayground+0xdfb95) (BuildId: dc419eb81c4ef89babd371b15b4ef9c1a4f8715b)

SUMMARY: ThreadSanitizer: data race /home/mhier/software/sources/CppPlayground/src/main.cc:19:8 in main::$_0::operator()() const
==================
1
2
3
4
5
6
7
8
9
ThreadSanitizer: reported 1 warnings
```

The above output has been generated with clang 18.1.3 on Ubuntu but the issue can be reproduced also with the latest clang 21.1 installed through `https://apt.llvm.org/llvm.sh`. In all cases I have been compiling and running this code on Ubuntu 24.04, hence I am using libstdc++ rather than libc++.

The problem goes away when:
- using `mx.lock()` instead of `try_lock_for()`,
- changing the `shared_timed_mutex` into a `timed_mutex` (despite we always lock the mutex exclusively!)
- changing to the boost equivalent `boost::shared_mutex`.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzsWltv47YS_jXMyyACRV39kAclqc8JcHZRdLcozpNBUWOLXYp0RcqX_voDUrKdeJ30st62B1jDcBRyOJz5NBp-4pBbK1ca8Y5k9yR7vOGDa01_17US-5vaNPu7jy3Cx7ZH3nzgWjr5K_ZgETsLzoBcadMjkJxa15CkIkllW95js3Cyw2bRDQ53JKdoYdtK0ULLNwg1ogZlxCdsYCO5H-76_cK3LJamJ6wkbEZyClw3IIy2-MuA2qk99Lg2vbOw5Mri7dpY6eQGoeGOQ88F2ojQitDq39gjSAscOqllxxXUgwNhurVChyBMg4A77v_1VocxJKfj94Gwe_-lFWGJ1EINDQJJHgYtrWuiliTfTSNedEtjXY-8m7pf9E2gjHBc6HcB4KNiqR10XGqPhL8v9x3f17gY9GCxIdkjyR7By_B-JQh7gFeFRMt7wirCKi-7IWwGpPCewRv3C7odSe5HSyDMswOSPAJ91soHZ8DR0H5UNXkxGs1yb8A0GwCMN9bKX3HhQB4VhssHiMP1CLx8Zmb4DFYhrgkrY-o_PjiSU28wxXwKGrtddBZJR-NE2xttJp9RGN1Ywsp8VPdSo1yGEIzNp3NLAFzbm-3JZWVWUiyw76ewZe9NiGzCYsLYmV5SPB6vd1OQPevudtGgx8HlaeRhkP97aAwNfxrQt-C8NpivQ_nngTzBeLLHDM677T3fHS6OvagbNQ2_jPGkMlw6Gv1sxkfvCPfYe8gPo-SD6dZSSb0C10o7ppStdC18_MA1oOa1wiZksH7Q2stJB1upFKx70wwCwbUIS6OU2fpeM7j14D7PRoRWYUY2H2xP2Lz2ts2V2nS3dt_VRvmMfBuXJKlghC-pgLCCZPfWcfHJZwJW-Mb3BuwgWlhKhWB6aGSPwpl-79Unj3_mS6ufqh_eP73_l9d_tkr4pmNiBsLKtWxI8pjFcR6nHluP9k-9dAhmCT6OIQXugO6K5fgRWAqo9zDmFfgYj-iEGGAJHVNkuMOEpQs6Xpo19twdV5HwGxYRB4TNW9MhYfOwvhE2t2bptrzHcDn0Ai1h84f1-nvF96veDLrxPb3wQ7jUkRAkqeIZSarSe3QmeU93SGleh1Bn5f0gVfPUBBxEGs-wLmOR4rKc1bxukiKu46xOcTkTMU-XZRFn9QQLYUkMGyObUwwvFlJvzCdcyG6tSPLge33q_wyD754_p8dRxrXe4c_lWR6-3uAXARZFPspkTdh8Jbz_uzJf5OmtknrY3a70QNg8Tg6CZz_TykbYXExpbhKupbOh3xvlV9Iq9zc1Ti-j2SyXdXYNNNkFIHu0g3IkebgA4bic7df4-bjLA1j5TwN2lr8NbHkVYJOzMD0QmYDYU7Cm9_zn2D8EynUR8wn2xbsT0nRQ5xH9pBvcLQ56DgJ_LczWNYvR0wA1mzGPdfIq1tlVsE6vCvPFPPm3gujTahy_CiK7CojZKyB-cNwdk-u1cD5FdD_ofwDEafpmnGI6uwbEOeAOxeBwobl_PZtMWPRmcFJ7KjCvvf7R5ds4vZWrTEh6-j9OIxbRZ3IXQFGytq6Z_L7dJMeFemqK41dACz-j6O_SMQE4Lv00IBgW_xeDI2uifGQAoqmTz2EUvCgajkWRoSiLLKVcNAWLyyWfzahIaROLWcrreIQxsJzve9xIM1gI7Oc3OJKPQDiF6xlLuhb1SejR_UsBVC-bLw2gYHllQS7B7nV4z5C_TvsE43vLS-_GlxlP-fWg_Fpw2basqQX_4uAeJ43_NuLpg694lXjGV3l62TfieUXimXwjnl-HeKbfiOdfRjxf40zfiOcfYkXfiOdXJp7FN-J5FeL5HyO4k0aDtBD2ED35fEYwo0uCK2VqrsLOYzL3X1a8YKpNQymFsThw2pi8p7t4iaU4zf7xsNnnZd1pyzD3JGLaSg3MqkfusDnjvsDdGUFcT0Ewyv8mUcxpmXz5Bt6BKC4Wq7Ppv1YInp7IC_LTU-ltuW1wyQflRg5U-LU6yd6MKqzpl0bVhAd7JQW-W1jHe7c41o-OYoOWvwy4WLv-1eQY8qePjWP35OGiQYUOf2PgmC3Zw0gnQqqsjsvSlDb_b5NG4elBUvyO23u6SclVXxjjtwlKPfvitZXQ6sOP795VP_z3d9Qgrrn_L_UffQ_8kjpLTGjFCK0SQquU0CojtMoJrQpCq5LQykNxwfmxYI4NxLDlvc-d9vNS1scWgddmg1MRClpuxyL9CrV3BpuxtCUU1yuIyyiOEjAafqwH7YZQW3ctgrR2QBBcQ41-5rHO1QBX1owKvJTiDq2bdLE4ikFq67hS2ISi4LBqgeS0dW5tA7JzwuZ87SKlNl1k-tVU_opsS3IawZMGrhQIbtHC07MTBuJYoXtehTtV604OsDSiqU8CLWqB8AS8g8F66RePDfTcv82Ca7n2PYen6YTiuje1wg5WBi3wLd_DtkU9rki3k0qS024XPatB5jQgMG3yvHYYgrCHoES0XK9GR8aDF5fOW4DUzsB4suJlB2Flg3YtHcIWgast39tQaA36xvo_7oQarNyg2ofy6-xsYhNka2OsA_xlkBuuUDs_WWh7ca7gMHF009wlzSyZ8Ru8i4u0LPMsmbGb9i4pBK1FU5QpbRI64_UsW6a0zvM0x7qu0xt5xyjLaE5ZHGd5wqJZnpUFS7OaJbOC1wVJKXZcqmOE3IRIvItTlhT0RvEalQ0nXBjTuB3jlDBGsseb_i6UUuthZUlKlbTOntQ46RTehYLu-ZGXN85P3Ay9unsZvivp2qGOhOmm4D2UcNe9-RmF8wu4N8qnn8nqzR37XwAAAP__8_VZkA">