[libc-commits] [libc] [libc] fix tls teardown while being used (PR #108229)

Schrodinger ZHU Yifan via libc-commits libc-commits at lists.llvm.org
Wed Sep 11 06:58:21 PDT 2024


https://github.com/SchrodingerZhu created https://github.com/llvm/llvm-project/pull/108229

None

>From 1ba4d36b6542e0b83378d7f404786b087fb2651b Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Wed, 11 Sep 2024 09:56:47 -0400
Subject: [PATCH] [libc] fix tls teardown while being used

---
 libc/src/stdlib/atexit.cpp      |  6 +++++-
 libc/src/stdlib/quick_exit.cpp  |  3 +++
 libc/startup/linux/do_start.cpp | 11 ++++++-----
 3 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/libc/src/stdlib/atexit.cpp b/libc/src/stdlib/atexit.cpp
index c8a15dd3cfef2d..799aad136bda5c 100644
--- a/libc/src/stdlib/atexit.cpp
+++ b/libc/src/stdlib/atexit.cpp
@@ -16,6 +16,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 constinit ExitCallbackList atexit_callbacks;
 Mutex handler_list_mtx(false, false, false, false);
+[[gnu::weak]] extern void teardown_main_tls();
 
 extern "C" {
 
@@ -24,8 +25,11 @@ int __cxa_atexit(AtExitCallback *callback, void *payload, void *) {
 }
 
 void __cxa_finalize(void *dso) {
-  if (!dso)
+  if (!dso) {
     call_exit_callbacks(atexit_callbacks);
+    if (teardown_main_tls)
+      teardown_main_tls();
+  }
 }
 
 } // extern "C"
diff --git a/libc/src/stdlib/quick_exit.cpp b/libc/src/stdlib/quick_exit.cpp
index a5abf3e05d1a13..29110b33afcf50 100644
--- a/libc/src/stdlib/quick_exit.cpp
+++ b/libc/src/stdlib/quick_exit.cpp
@@ -16,9 +16,12 @@
 namespace LIBC_NAMESPACE_DECL {
 
 extern ExitCallbackList at_quick_exit_callbacks;
+[[gnu::weak]] extern void teardown_main_tls();
 
 [[noreturn]] LLVM_LIBC_FUNCTION(void, quick_exit, (int status)) {
   call_exit_callbacks(at_quick_exit_callbacks);
+  if (teardown_main_tls)
+    teardown_main_tls();
   internal::exit(status);
 }
 
diff --git a/libc/startup/linux/do_start.cpp b/libc/startup/linux/do_start.cpp
index 72060b4adb2148..ff104c7f0d1d2f 100644
--- a/libc/startup/linux/do_start.cpp
+++ b/libc/startup/linux/do_start.cpp
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 #include "startup/linux/do_start.h"
+#include "config/linux/app.h"
 #include "include/llvm-libc-macros/link-macros.h"
 #include "src/__support/OSUtil/syscall.h"
 #include "src/__support/macros/config.h"
@@ -60,6 +61,10 @@ static void call_fini_array_callbacks() {
 }
 
 static ThreadAttributes main_thread_attrib;
+static TLSDescriptor tls;
+// We separate teardown_main_tls from callbacks as callback function themselves
+// may require TLS.
+void teardown_main_tls() { cleanup_tls(tls.addr, tls.size); }
 
 [[noreturn]] void do_start() {
   auto tid = syscall_impl<long>(SYS_gettid);
@@ -122,7 +127,6 @@ static ThreadAttributes main_thread_attrib;
 
   // This descriptor has to be static since its cleanup function cannot
   // capture the context.
-  static TLSDescriptor tls;
   init_tls(tls);
   if (tls.size != 0 && !set_thread_ptr(tls.tp))
     syscall_impl<long>(SYS_exit, 1);
@@ -130,10 +134,7 @@ static ThreadAttributes main_thread_attrib;
   self.attrib = &main_thread_attrib;
   main_thread_attrib.atexit_callback_mgr =
       internal::get_thread_atexit_callback_mgr();
-  // We register the cleanup_tls function to be the last atexit callback to be
-  // invoked. It will tear down the TLS. Other callbacks may depend on TLS (such
-  // as the stack protector canary).
-  atexit([]() { cleanup_tls(tls.addr, tls.size); });
+
   // We want the fini array callbacks to be run after other atexit
   // callbacks are run. So, we register them before running the init
   // array callbacks as they can potentially register their own atexit



More information about the libc-commits mailing list