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

    <tr>
        <th>Summary</th>
        <td>
            libcxx: race condition on weak_ptr/shared_ptr destructor
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            libc++
      </td>
    </tr>

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

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

<pre>
    I've been running several tests involving sharing `std::shared_ptr` and `std::weak_ptr` objects under thread sanitizer. I've been getting a bunch of race condition reports. The code under test shares a single, constant value allocated using `std::make_shared` by copying a bunch of `std::shared_ptr` and `std::weak_ptr` objects to several threads.

I've been able to isolate a minimum reproducible example with clang-18 and libc++-18 packages under Ubuntu 24.04. Please find a full Dockerfile containing self-contained instructions on how to reproduce the issue at the bottom of this message.

Interestingly, the race condition is only reported when combining `std::shared_ptr` and `std::weak_ptr` objects. Commenting the branch creating the weak pointers makes the race condition disappear.

Please let me know if I can help anyhow.

Dockerfile for reproduction:

```docker
FROM ubuntu:24.04

RUN DEB_FRONTEND=noninteractive apt-get update && apt-get install -y \
 clang-18 libc++-18-dev libc++abi-18-dev

COPY <<EOF /repro/main.cpp

#include <memory>
#include <thread>
#include <vector>

void perform()
{
    // Setup
    auto ptr = std::make_shared<int>(0);

    std::vector<std::thread> threads;
 for (int i = 0; i < 16; ++i)
    {
        if (i % 2)
        {
 threads.emplace_back([ptr]() mutable {
 std::this_thread::yield();
                ptr.reset();
 });
        }
        else
        {
 threads.emplace_back([w = std::weak_ptr<int>(ptr)]() mutable {
 std::this_thread::yield();
                w.reset();
 });
        }
    }

    ptr.reset();

    for (auto& t : threads)
        t.join();
}

int main()
{
    for (int i = 0; i < 10000; ++i)
        perform();
}

EOF

RUN clang++-18 -fsanitize=thread -std=c++20 -g -O0 -stdlib=libc++ -o /repro/main /repro/main.cpp
RUN TSAN_OPTIONS=halt_on_error=1 /repro/main
```

TSAN report:

```
2.954 ==================
2.954 WARNING: ThreadSanitizer: data race (pid=7)
2.954   Write of size 8 at 0x720800002720 by thread T25791:
2.954     #0 operator delete(void*) <null> (main+0xe130d) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.954     #1 void std::__1::__libcpp_operator_delete[abi:ne180100]<void*>(void*) /usr/lib/llvm-18/bin/../include/c++/v1/new:280:3 (main+0xe75f5) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.955     #2 void std::__1::__do_deallocate_handle_size[abi:ne180100]<>(void*, unsigned long) /usr/lib/llvm-18/bin/../include/c++/v1/new:302:10 (main+0xe7571) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.955     #3 std::__1::__libcpp_deallocate[abi:ne180100](void*, unsigned long, unsigned long) /usr/lib/llvm-18/bin/../include/c++/v1/new:317:12 (main+0xe74ba) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.955     #4 std::__1::allocator<std::__1::__shared_ptr_emplace<int, std::__1::allocator<int>>>::deallocate[abi:ne180100](std::__1::__shared_ptr_emplace<int, std::__1::allocator<int>>*, unsigned long) /usr/lib/llvm-18/bin/../include/c++/v1/__memory/allocator.h:139:7 (main+0xe8aba) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.955 #5 std::__1::allocator_traits<std::__1::allocator<std::__1::__shared_ptr_emplace<int, std::__1::allocator<int>>>>::deallocate[abi:ne180100](std::__1::allocator<std::__1::__shared_ptr_emplace<int, std::__1::allocator<int>>>&, std::__1::__shared_ptr_emplace<int, std::__1::allocator<int>>*, unsigned long) /usr/lib/llvm-18/bin/../include/c++/v1/__memory/allocator_traits.h:289:9 (main+0xe8a45) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.955 #6 std::__1::__shared_ptr_emplace<int, std::__1::allocator<int>>::__on_zero_shared_weak() /usr/lib/llvm-18/bin/../include/c++/v1/__memory/shared_ptr.h:294:5 (main+0xe877c) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.955 #7 std::__1::weak_ptr<int>::~weak_ptr() /usr/lib/llvm-18/bin/../include/c++/v1/__memory/shared_ptr.h:1401:15 (main+0xe78d6) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.955 #8 std::__1::weak_ptr<int>::reset() /usr/lib/llvm-18/bin/../include/c++/v1/__memory/shared_ptr.h:1450:3 (main+0xe77b3) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.955 #9 perform()::$_1::operator()() /repro/main.cpp:25:19 (main+0xe38e2) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.955     #10 decltype(std::declval<perform()::$_1>()()) std::__1::__invoke[abi:ne180100]<perform()::$_1>(perform()::$_1&&) /usr/lib/llvm-18/bin/../include/c++/v1/__type_traits/invoke.h:344:25 (main+0xe3855) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.955 #11 void std::__1::__thread_execute[abi:ne180100]<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, perform()::$_1>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, perform()::$_1>&, std::__1::__tuple_indices<...>) /usr/lib/llvm-18/bin/../include/c++/v1/__thread/thread.h:193:3 (main+0xe380d) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.955     #12 void* std::__1::__thread_proxy[abi:ne180100]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, perform()::$_1>>(void*) /usr/lib/llvm-18/bin/../include/c++/v1/__thread/thread.h:202:3 (main+0xe3452) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.955 
2.955 Previous read of size 8 at 0x720800002720 by main thread:
2.955     #0 std::__1::__shared_count::__release_shared[abi:ne180100]() /usr/lib/llvm-18/bin/../include/c++/v1/__memory/shared_ptr.h:157:7 (main+0xe8ce0) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.955 #1 std::__1::__shared_weak_count::__release_shared[abi:ne180100]() /usr/lib/llvm-18/bin/../include/c++/v1/__memory/shared_ptr.h:186:25 (main+0xe8c79) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.955 #2 std::__1::shared_ptr<int>::~shared_ptr[abi:ne180100]() /usr/lib/llvm-18/bin/../include/c++/v1/__memory/shared_ptr.h:648:17 (main+0xe4136) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.956 #3 std::__1::shared_ptr<int>::reset[abi:ne180100]() /usr/lib/llvm-18/bin/../include/c++/v1/__memory/shared_ptr.h:698:50 (main+0xe3ed3) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.956 #4 perform() /repro/main.cpp:30:9 (main+0xe1cab) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.956     #5 main /repro/main.cpp:39:9 (main+0xe2060) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.956 
2.956   Thread T25791 (tid=25799, running) created by main thread at:
2.956     #0 pthread_create <null> (main+0x616df) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.956     #1 std::__1::__libcpp_thread_create[abi:ne180100](unsigned long*, void* (*)(void*), void*) /usr/lib/llvm-18/bin/../include/c++/v1/__threading_support:317:10 (main+0xe4599) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.956 #2 std::__1::thread::thread<perform()::$_1, void>(perform()::$_1&&) /usr/lib/llvm-18/bin/../include/c++/v1/__thread/thread.h:212:14 (main+0xe324e) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.956 #3 std::__1::thread* std::__1::construct_at[abi:ne180100]<std::__1::thread, perform()::$_1, std::__1::thread*>(std::__1::thread*, perform()::$_1&&) /usr/lib/llvm-18/bin/../include/c++/v1/__memory/construct_at.h:41:46 (main+0xe3171) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.956 #4 std::__1::thread* std::__1::__construct_at[abi:ne180100]<std::__1::thread, perform()::$_1, std::__1::thread*>(std::__1::thread*, perform()::$_1&&) /usr/lib/llvm-18/bin/../include/c++/v1/__memory/construct_at.h:49:10 (main+0xe3105) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.956 #5 void std::__1::allocator_traits<std::__1::allocator<std::__1::thread>>::construct[abi:ne180100]<std::__1::thread, perform()::$_1, void, void>(std::__1::allocator<std::__1::thread>&, std::__1::thread*, perform()::$_1&&) /usr/lib/llvm-18/bin/../include/c++/v1/__memory/allocator_traits.h:305:5 (main+0xe30a1) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.956 #6 void std::__1::vector<std::__1::thread, std::__1::allocator<std::__1::thread>>::__construct_one_at_end[abi:ne180100]<perform()::$_1>(perform()::$_1&&) /usr/lib/llvm-18/bin/../include/c++/v1/vector:902:5 (main+0xe2ea4) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.957     #7 std::__1::thread& std::__1::vector<std::__1::thread, std::__1::allocator<std::__1::thread>>::emplace_back<perform()::$_1>(perform()::$_1&&) /usr/lib/llvm-18/bin/../include/c++/v1/vector:1508:5 (main+0xe1f6c) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.957     #8 perform() /repro/main.cpp:23:21 (main+0xe1c62) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.957     #9 main /repro/main.cpp:39:9 (main+0xe2060) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2)
2.957 
2.957 SUMMARY: ThreadSanitizer: data race (/repro/main+0xe130d) (BuildId: 729198def45d306742914bd873c6632f97bd2eb2) in operator delete(void*)
2.957 ==================
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsW0tv4zgS_jXMhYghkXoecnDseNGHSRrdGQzmJNBi2eZEJrUS5SRz2N--ICXZsiJ5eruVTA-wQZCWKD6qvnqwqshmZSm2EuAG-bfIX16xSu9UccMkK_SOZVdrxV9vPiESHgCvASQuKimF3OISDlCwDGsodYmFPKjsYNt3rDD_osApNUd0jujctAFPcl2gwMFM8rOvz8Ce2m9q_QekusSV5FBgvSuAcVwyKbT4E4oZ7lKyBa3NSgyvK5nusNrggqWAUyW50EJJXECuCl3O8OPONHNo54VSW0KhxAyXQm4zQGRhRpaaSY0PLKsAsyxTKdPAcVX2WdqzJ0hqvgzd61ecqvy1R86PYaDVCWQLRDlDzhI58_pvFwq2zsD0F6XKmAbM8F5Isa_2BoJC8SoVpge8sH2eAX4WeofTjMnttRtZWjKxThG5ReTWtOQsfWJbaMXw67qSusLEmzneDH_OgJWAN0JyzPCmyjK8VOkTFBuRWfA1E42GZJvr5h04FrLURZUawZRYSbxTz4bklkDAegdYlKUBXtuXtdJa7Q2QeidKvIeyZFs4B0FqKKA0epC9GhGacT0tEGa57LXRBuD4eQcSp2q_run8ISnN8ELt9yCtJlqiC2aknxbAjm1mHM6VMMSW2KhOOUQoFyXLc2DFGYsN3hlovAf8JNUzFhv8CadM4h1kOWbydaeez8Z0BLJRxRFjs4rhpNMTBU79y-2QunH15eEXXFmpIzq3cu-O-fLrPV7e3SarLw_3j3f3S0SXUknLHUu1OABmub7egsZVzo06IhIgEhxbjSawLMPXrxj5i3rOkzqeqeI1h0Onha1F09ilZ_Hw-XeM6ALRxd3DCiOysgwjstozIWdpnp9xTKiQaVZxMGP2sFfFK6J3Qx9rsxv5eIBUq-L00f49KMFxDsVGFXtEIkTi5mt42_CJsSEQkRX-CrrKT62s0grnusCILvGgn6ELIbVZkESOmZnedpc2cxyHtcQtji1HXlpnchxuVQSRSEiNhV3dQfTWPi6wG5jnGn1xZMdy0WXJ_IiNnQUj4mNy1vW8e-vMYJ9nLIVkzdIng5V_a0zLX9a44X2lrVs7DezwIsqkZcg0vArIeIM37ZHV_uS6mBVQgu73Q-FyaJxpPmuArIT_nafnc3keXUhHmOaVxO_H-fP38318OTWN4Xjq0eiTUWhj9hojekTojV7o2R9KyP5c58sazTSmPGpRFzXYcRxnTIktQ2fmOkLC3cOq7wKtxzptmtebNk5BdNlELtdWcMvGexEHX2_x9YNj2zOxRnR58m34WvVd17grM-s_fp3fJw-fHz893H9FdLljmU6UTKAojOUv3f7onsPvsmOmavbHsf2hfiWz2PcMwt_z25nht_mX-0_3_zKK8Wih-trGeKaJM83qzdFYhzAQhkex1RNg_FshNJjgoBR_Ao5M0OC8hMSJjLxJSGxQ1sjhkfhh7B5Za6cwrpg6WOVQMK0KzCEDDYhExo0jMjfGiOhCVllmHCciUa2Ft84LuNTh9juJbiuR8U_GIHFIYjeOOGw8n1MnCD0Su96aRyFNg4CSTRyuOYE1ecONJcXFdv84WnuSuO2D0ZM8T1pSk4ZU32yJiM4luJHjOo5xInTRkm-9S5cXsqrKApGV0T2yyrLD_tqNEFmtDVer2QyRVbPDIbJq9BKR1cFFZCXh2QQDkYPonJ5jEfobfyIs_BYLMo4FVwmHNjhPdkzyDBKjBSNw9HBY4ErapIfjTBkLngQY6hBE567TRyZ0p0aGXlKQEzCDYFyC4Z1wcUODC-nh4q3Z1Lh4A7g0YJyHQh3UTvF-0mzdzcZMFn8xW7N7N7_m619C_14EvIdSJ0kTGZPVcdHZzkiSxojOw3NxRmxCcSJC_Uu8J7pgQpeDEv0oeX-_yD-IQpNxDQ34Z2lcI2qreCQyihf3Fc-bbudBhAbvBlnTR8nkTyhUO6VJB5qofyrwTsTWsMUeonO_B1sYplPCFg7A8DbTsc3_Oba_K9uu5xg63B7jYcSDKRmPvp3xTs70fkz7Q9FZuKZT8hz3MybDHSJey38bozafjxy_yWTonPiG6p5N0wjI1LGB62AOaaZfc-h6ZdN2YBmii3GW7rp8GLqGPISQB_U0Fn9ennv0qy2aTaAthul2zzQdDaVWXajnWRn04fcndanuhaymTs8SeIG0Gs1m3g6spPh3BY2NXZi3LjgPe2kOG1Zluk2kvmWeZu9bXND_u8E9X1d5NrzET83JaAhh-UmE5CIFE4fNZjM74MdVta5skVX9UDu1mL71aTSaLPs--Yg65URkfklX80K9vH6zpv4zJT9p3WBYqsSmy32pev50nr_7_LmAg1BViW016C9qRrbydqqxvlUU51KQmKpK6ratAHt40xbwh3OE9wwI_HAgWUvBmdTBX4LDBkM_FyZRMLDrRWkYTwkKGQClc7jYi4k7Xz4cj8CLDCo9JfFcOlWgHIwVrUbxqEPlj0ciNkj4vRIeBT5V-BzUZaoz1zsSGVPnbbLrpmw9GSWNL_Px6EEDndOBjJs4wVTeI8DnBD12i_VmAW1L_-Y1NltWc_XErG6P14H33DVm-sxjByePnTfbYD1wrKofuAHfTA3xsH9s6rVnZI2ofK_OYmsvbaRilWhe5yenHbvTY7L9W8htUlZ5c0bUlHV7tuL58VReNBjzot3Tz_Z5PMVqgfigVGso0nHtwYDX8yrEg_f2ry01Q_GsvepkIsKEDXvawWi2mfBC9DgYpx4JGU2Qjh0uzj2RlI7-vwuClZVn6PGCnqjcyc5wgrFzikuiSpL_C2tQWPGAB6KuM1X1Iqj3x5HixQTHEafrRW3gc-RxYinXe0HXFX4_rWNlgb9JLQbPCqjjvy16U4dNasfBmGq8vXw1IK4fV5auX1ASEqYTkMMJ1d9cg2wBmcc26-_JhQDzJpJL2MZcQwcSLfZDZzwfJLKz62E_i1Bc34neSsXdBFMdER2lEn1T6kOojZr6uU8wVWnoSE78N-Y-Ie4-f_31l1_mX37_lutQ_Utd01xGwkJevAZ1RvgP3P46Xie74jeUxzRmV3DjhiSMIxoQ92p34zgRj90wYiHnabymabDmgQOMR64X-sHmStwQh3iu41A3JqHjzljoxIzEPIxdzjfxBnkO7JnIZsYeZqrYXtlb5Teu6zpedJWxNWSl_f8OhJyu3yFCkL-8Km6sFa2rbYk8JxOlLk_zaKEzuDFjXl4MwL3720ri0-Fmp7iAOdRuWhVXVZHd7LTOS2vNK0RWW6F31XqWqn1jwq0l54X6A1JtbNjQXyKyalg43JD_BgAA__8-hv5H">