[libcxx-commits] [PATCH] D155278: [libc++][mingw] TLS cleanup on windows

Karl-Johan Johnsson via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jul 14 02:30:57 PDT 2023


kalle-llvm created this revision.
kalle-llvm added a reviewer: mstorsjo.
Herald added a project: All.
kalle-llvm requested review of this revision.
Herald added projects: libc++, libc++abi.
Herald added a subscriber: libcxx-commits.
Herald added a reviewer: libc++.
Herald added a reviewer: libc++abi.

On windows, when libc++ is statically linked into a dll the tls-key used for __cxa_eh_globals must be freed when the dll is unloaded.  Otherwise the callback registered for the tls-key will remain in place but point to non-existing code and the process will crash as soon as a thread exits.

This will happen if libc++ is statically linked into the dll or if the main application doesn't use libc++ (so that is is unloaded when the dll is unloaded).

I've made a function __libcpp_tls_destroy() that is registered with atexit() that frees the tls-key.  I did this conditionally on _LIBCPP_HAS_THREAD_API_WIN32 since I'm not sure how this should be handled for the other thread models.

I think a similar problem exists with the tls-key in __thread_specific_ptr, but a comment in the destructor (thread.h line 103) says that the missing cleanup is intentional in the pthreads case.  And this destructor is inlined so I guess adding a cleanup there would be an ABI break?


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D155278

Files:
  libcxx/include/__threading_support
  libcxx/src/support/win32/thread_win32.cpp
  libcxxabi/src/cxa_exception_storage.cpp


Index: libcxxabi/src/cxa_exception_storage.cpp
===================================================================
--- libcxxabi/src/cxa_exception_storage.cpp
+++ libcxxabi/src/cxa_exception_storage.cpp
@@ -64,9 +64,18 @@
             abort_message("cannot zero out thread value for __cxa_get_globals()");
     }
 
+#if defined(_LIBCPP_HAS_THREAD_API_WIN32)
+    void destroy_() {
+        std::__libcpp_tls_destroy(key_);
+    }
+#endif
+
     void construct_() {
         if (0 != std::__libcpp_tls_create(&key_, destruct_))
             abort_message("cannot create thread specific key for __cxa_get_globals()");
+#if defined(_LIBCPP_HAS_THREAD_API_WIN32)
+        atexit(destroy_);
+#endif
     }
 } // namespace
 
Index: libcxx/src/support/win32/thread_win32.cpp
===================================================================
--- libcxx/src/support/win32/thread_win32.cpp
+++ libcxx/src/support/win32/thread_win32.cpp
@@ -259,6 +259,11 @@
   return 0;
 }
 
+void __libcpp_tls_destroy(__libcpp_tls_key __key)
+{
+  FlsFree(__key);
+}
+
 void *__libcpp_tls_get(__libcpp_tls_key __key)
 {
   return FlsGetValue(__key);
Index: libcxx/include/__threading_support
===================================================================
--- libcxx/include/__threading_support
+++ libcxx/include/__threading_support
@@ -240,6 +240,9 @@
 int __libcpp_tls_create(__libcpp_tls_key* __key,
                         void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
 
+_LIBCPP_THREAD_ABI_VISIBILITY
+void __libcpp_tls_destroy(__libcpp_tls_key __key);
+
 _LIBCPP_THREAD_ABI_VISIBILITY
 void *__libcpp_tls_get(__libcpp_tls_key __key);
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D155278.540326.patch
Type: text/x-patch
Size: 1630 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20230714/0dd24a39/attachment.bin>


More information about the libcxx-commits mailing list