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