[libc-commits] [libc] [libc] Remove (weak) __cxa_thread_finalize (PR #216081)

Pavel Labath via libc-commits libc-commits at lists.llvm.org
Thu Aug 13 08:14:43 PDT 2026


https://github.com/labath created https://github.com/llvm/llvm-project/pull/216081

Unlike __cxa_thread_atexit(_impl), this function is not a part of the ABI as the process of calling the thread exit callbacks is an implementation detail. Additionally, the weak definition gets in the way of refactoring the thread code as the linker will not extract an object from the archive if the dependency is already satisfied by a weak definition.

Instead of a weak definition, I use a preprocessor macro to determine whether we need to call the thread cleanup function (i.e., whether the target supports threads).

>From 81f8775e60742e528d7f1863d84053e3f658c798 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Thu, 13 Aug 2026 14:57:38 +0000
Subject: [PATCH] [libc] Remove (weak) __cxa_thread_finalize

Unlike __cxa_thread_atexit(_impl), this function is not a part of the
ABI as the process of calling the thread exit callbacks is an
implementation detail. Additionally, the weak definition gets in the way
of refactoring the thread code as the linker will not extract an object
from the archive if the dependency is already satisfied by a weak
definition.

Instead of a weak definition, I use a preprocessor macro to determine
whether we need to call the thread cleanup function (i.e., whether the
target supports threads).
---
 libc/src/__support/threads/thread.cpp |  2 --
 libc/src/stdlib/CMakeLists.txt        | 10 ++++++++++
 libc/src/stdlib/exit.cpp              | 24 +++++++-----------------
 3 files changed, 17 insertions(+), 19 deletions(-)

diff --git a/libc/src/__support/threads/thread.cpp b/libc/src/__support/threads/thread.cpp
index babcfdc5aea15..31c230a45b573 100644
--- a/libc/src/__support/threads/thread.cpp
+++ b/libc/src/__support/threads/thread.cpp
@@ -164,8 +164,6 @@ void call_atexit_callbacks(ThreadAttributes *attrib) {
   }
 }
 
-extern "C" void __cxa_thread_finalize() { call_atexit_callbacks(self.attrib); }
-
 } // namespace internal
 
 cpp::optional<unsigned int> new_tss_key(TSSDtor *dtor) {
diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index a0e8cd356a212..1d45a70d1a26f 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -811,12 +811,22 @@ if(NOT LIBC_TARGET_OS_IS_BAREMETAL)
   )
 endif()
 
+set(exit_compile_options "")
+if(TARGET libc.src.__support.threads.thread)
+  list(APPEND exit_deps
+    libc.src.__support.threads.thread
+  )
+  libc_add_definition(exit_compile_options "LIBC_COPT_SUPPORT_THREADS")
+endif()
+
 add_entrypoint_object(
   exit
   SRCS
     exit.cpp
   HDRS
     exit.h
+  COMPILE_OPTIONS
+    ${exit_compile_options}
   DEPENDS
     ${exit_deps}
 )
diff --git a/libc/src/stdlib/exit.cpp b/libc/src/stdlib/exit.cpp
index db6a8f1280902..6f6758aba5896 100644
--- a/libc/src/stdlib/exit.cpp
+++ b/libc/src/stdlib/exit.cpp
@@ -11,29 +11,19 @@
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
 
+#ifdef LIBC_COPT_SUPPORT_THREADS
+#include "src/__support/threads/thread.h"
+#endif
+
 namespace LIBC_NAMESPACE_DECL {
 
 extern "C" void __cxa_finalize(void *);
 
-// exit() needs to clean up TLS and call associated destructors.
-//
-// The weak no-op implementation is in the same TU with its caller for the case
-// where the real definition is not linked in. This is preferable over weak
-// undefined symbol with a check since that requires a GOT slot.
-//
-// The strong implementation is in libc/src/__support/threads/thread.cpp
-// but not every platform supports threads (e.g. baremetal) in which case the
-// the no-op implementation is sufficient.
-//
-// TODO: Strictly speaking, it is not valid to call exit in overlay mode
-//       as we have no way to ensure system libc will call the TLS destructors.
-//       We should run exit related tests in hermetic mode but this is currently
-//       blocked by https://github.com/llvm/llvm-project/issues/133925.
-extern "C" [[gnu::weak]] void __cxa_thread_finalize() {}
-
 // TODO: use recursive mutex to protect this routine.
 [[noreturn]] LLVM_LIBC_FUNCTION(void, exit, (int status)) {
-  __cxa_thread_finalize();
+#ifdef LIBC_COPT_SUPPORT_THREADS
+  internal::call_atexit_callbacks(self.attrib);
+#endif
   __cxa_finalize(nullptr);
   internal::exit(status);
 }



More information about the libc-commits mailing list