[libc++] Avoid lifetime UB in __thread_local_data()
authorVitaly Buka <vitalybuka@google.com>
Fri, 1 Apr 2022 04:58:44 +0000 (21:58 -0700)
committerVitaly Buka <vitalybuka@google.com>
Mon, 25 Apr 2022 21:56:44 +0000 (14:56 -0700)
commit0c99575df4a9395e32bf1121c103616ba812accb
tree4b286027b40dfb3fe2df8b2913b3498337e2d12c
parent09e75d3f0996d58cba7477d3d1f04b1e8e12c595
[libc++] Avoid lifetime UB in __thread_local_data()

Detected on many lld tests with -fsanitize-memory-use-after-dtor.
Also https://lab.llvm.org/buildbot/#/builders/sanitizer-x86_64-linux-fast after D122869 will report a lot of them.

Threads may outlive static variables. Even if ~__thread_specific_ptr() does nothing, lifetime of members ends with ~ and accessing the value is UB https://eel.is/c++draft/basic.life#1

```
==9214==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x557e1cec4539 in __libcpp_tls_set ../include/c++/v1/__threading_support:428:12
    #1 0x557e1cec4539 in set_pointer ../include/c++/v1/thread:196:5
    #2 0x557e1cec4539 in void* std::__msan::__thread_proxy<
      std::__msan::tuple<...>, llvm::parallel::detail::(anonymous namespace)::ThreadPoolExecutor::ThreadPoolExecutor(llvm::ThreadPoolStrategy)::'lambda'()::operator()() const::'lambda'()> >(void*) ../include/c++/v1/thread:285:27

  Memory was marked as uninitialized
    #0 0x557e10a0759d in __sanitizer_dtor_callback compiler-rt/lib/msan/msan_interceptors.cpp:940:5
    #1 0x557e1d8c478d in std::__msan::__thread_specific_ptr<std::__msan::__thread_struct>::~__thread_specific_ptr() libcxx/include/thread:188:1
    #2 0x557e10a07dc0 in MSanCxaAtExitWrapper(void*) compiler-rt/lib/msan/msan_interceptors.cpp:1151:3
```

The test needs D123979 or  -fsanitize-memory-param-retval enabled by default.

Reviewed By: ldionne, #libc

Differential Revision: https://reviews.llvm.org/D122864
libcxx/src/thread.cpp
libcxx/test/libcxx/thread/thread.threads/create_late.pass.cpp [new file with mode: 0644]