This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 7fe245e7bfe libs/libc/stdlib: Call the atexit functions before the TLS 
destructors.
7fe245e7bfe is described below

commit 7fe245e7bfef8ad4a47de56256ecc45c8454a915
Author: Marco Casaroli <[email protected]>
AuthorDate: Mon Oct 12 01:58:28 2026 +0200

    libs/libc/stdlib: Call the atexit functions before the TLS destructors.
    
    exit() and quick_exit() ran the destructors of the thread-specific
    data first.  An exit function that used thread-specific data, or a
    __thread variable, which emulated TLS keeps there, then saw the data
    of a new thread: a program that held a lock and recorded it in a
    __thread flag locked it again from its exit function and failed with
    EDEADLK.
    
    Call the exit functions first, while the data of the thread is still
    valid.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 libs/libc/stdlib/lib_exit.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/libs/libc/stdlib/lib_exit.c b/libs/libc/stdlib/lib_exit.c
index 460bee9f828..79f54404245 100644
--- a/libs/libc/stdlib/lib_exit.c
+++ b/libs/libc/stdlib/lib_exit.c
@@ -101,14 +101,16 @@ void exit(int status)
 
   tls_cleanup_popall(tls_get_info());
 
+  /* Run the registered exit functions.  They run before the destructors
+   * of the thread-specific data, which they may still use.
+   */
+
+  atexit_call_exitfuncs(status, false);
+
 #if defined(CONFIG_TLS_NELEM) && CONFIG_TLS_NELEM > 0
   tls_destruct();
 #endif
 
-  /* Run the registered exit functions */
-
-  atexit_call_exitfuncs(status, false);
-
 #if defined(CONFIG_LIBC_DLFCN) && defined(CONFIG_BUILD_PROTECTED)
   /* Close what dlopen() left open.  The kernel cannot reach this registry.
    * A flat build does it in the kernel, after the last thread.  A kernel
@@ -162,14 +164,16 @@ void quick_exit(int status)
 
   tls_cleanup_popall(tls_get_info());
 
+  /* Run the registered exit functions.  They run before the destructors
+   * of the thread-specific data, which they may still use.
+   */
+
+  atexit_call_exitfuncs(status, true);
+
 #if defined(CONFIG_TLS_NELEM) && CONFIG_TLS_NELEM > 0
   tls_destruct();
 #endif
 
-  /* Run the registered exit functions */
-
-  atexit_call_exitfuncs(status, true);
-
   /* Then perform the exit */
 
   _exit(status);

Reply via email to