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);