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

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

commit eeab8c09c7a3f309697cf077211444c28365c50f
Author: Marco Casaroli <[email protected]>
AuthorDate: Tue Oct 20 20:45:01 2026 +0200

    libs/libc/tls: Repeat the key destructors as POSIX requires.
    
    <limits.h> did not define PTHREAD_DESTRUCTOR_ITERATIONS, and
    tls_destruct() called each key destructor once.  It also cleared the
    value after the call, so a value that a destructor set again was lost
    without a second call.
    
    Clear the value before the call, and repeat while a destructor ran, up
    to PTHREAD_DESTRUCTOR_ITERATIONS (4, the POSIX minimum) passes.
    Define PTHREAD_DESTRUCTOR_ITERATIONS in <limits.h>.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 include/limits.h             |  2 ++
 libs/libc/tls/tls_destruct.c | 32 ++++++++++++++++++++++++--------
 2 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/include/limits.h b/include/limits.h
index 25189e98a2b..e71d96e6ac6 100644
--- a/include/limits.h
+++ b/include/limits.h
@@ -276,6 +276,8 @@
 #  define PTHREAD_KEYS_MAX                      CONFIG_TLS_NELEM
 #endif
 
+#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+
 /* Required for readv() and writev() */
 
 /* There really is no upper limit on the number of vectors */
diff --git a/libs/libc/tls/tls_destruct.c b/libs/libc/tls/tls_destruct.c
index d968d707cba..dc8815aa7bb 100644
--- a/libs/libc/tls/tls_destruct.c
+++ b/libs/libc/tls/tls_destruct.c
@@ -27,6 +27,8 @@
 #include <nuttx/config.h>
 
 #include <assert.h>
+#include <limits.h>
+#include <stdbool.h>
 
 #include <nuttx/tls.h>
 
@@ -54,23 +56,37 @@ void tls_destruct(void)
 {
   FAR struct task_info_s *info = task_get_info();
   FAR struct tls_info_s *tls = tls_get_info();
-  FAR void *tls_elem_ptr = NULL;
+  FAR void *tls_elem_ptr;
   tls_dtor_t destructor;
+  bool again = true;
+  int iteration;
   int candidate;
 
   DEBUGASSERT(info != NULL);
 
-  for (candidate = CONFIG_TLS_NELEM - 1; candidate >= 0; candidate--)
-    {
-      /* Is this candidate index available? */
+  /* A destructor may set a value again: repeat, as POSIX requires */
 
-      tls_elem_ptr = (FAR void *)tls->tl_elem[candidate];
-      destructor = info->ta_tlsdtor[candidate];
-      if (tls_elem_ptr && destructor)
+  for (iteration = 0; again && iteration < PTHREAD_DESTRUCTOR_ITERATIONS;
+       iteration++)
+    {
+      again = false;
+      for (candidate = CONFIG_TLS_NELEM - 1; candidate >= 0; candidate--)
         {
-          destructor(tls_elem_ptr);
+          tls_elem_ptr = (FAR void *)tls->tl_elem[candidate];
+          destructor = info->ta_tlsdtor[candidate];
+          tls->tl_elem[candidate] = 0;
+          if (tls_elem_ptr && destructor)
+            {
+              destructor(tls_elem_ptr);
+              again = true;
+            }
         }
+    }
 
+  /* Clear the values that the last destructors set */
+
+  for (candidate = 0; candidate < CONFIG_TLS_NELEM; candidate++)
+    {
       tls->tl_elem[candidate] = 0;
     }
 }

Reply via email to