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 d9801ca71897908a9a123ad23052a9d3969ad01b
Author: Marco Casaroli <[email protected]>
AuthorDate: Tue Oct 20 21:02:17 2026 +0200

    include/pthread.h: Do not hide pthread_cleanup_push() in a macro.
    
    With CONFIG_TLS_NCLEANUP=0 there is no cleanup stack, and
    pthread_cleanup_push() and pthread_cleanup_pop() were empty macros.  A
    program compiled and linked, but its cleanup handlers never ran: not at
    pthread_exit(), not at a cancellation, and not at
    pthread_cleanup_pop(1), where POSIX requires the handler to run.
    
    Declare the functions in every configuration.  With
    CONFIG_TLS_NCLEANUP=0 the library does not have them, so a program
    that uses cleanup handlers fails to link.  That is intended: a version
    that links could not run the handlers either, and a link error is
    better than handlers that are silently lost.  The fix is to set
    CONFIG_TLS_NCLEANUP > 0.  The read-write lock functions push a cleanup
    handler only when the cleanup stack exists, as before.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 include/pthread.h                         | 8 ++------
 libs/libc/pthread/pthread_rwlock_rdlock.c | 6 ++++++
 libs/libc/pthread/pthread_rwlock_wrlock.c | 6 ++++++
 libs/libc/tls/Kconfig                     | 3 +++
 4 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/include/pthread.h b/include/pthread.h
index 4d2187d8571..f8d7868bcdc 100644
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -575,16 +575,12 @@ int  pthread_setcanceltype(int type, FAR int *oldtype);
 void pthread_testcancel(void);
 
 /* A thread may set up cleanup functions to execute when the thread exits or
- * is canceled.
+ * is canceled.  They need CONFIG_TLS_NCLEANUP > 0: without it, a program
+ * that calls them does not link.
  */
 
-#if CONFIG_TLS_NCLEANUP > 0
 void pthread_cleanup_pop(int execute);
 void pthread_cleanup_push(pthread_cleanup_t routine, FAR void *arg);
-#else
-#  define pthread_cleanup_pop(execute) ((void)(execute))
-#  define pthread_cleanup_push(routine,arg) ((void)(routine), (void)(arg))
-#endif
 
 /* A thread can await termination of another thread and retrieve the return
  * value of the thread.
diff --git a/libs/libc/pthread/pthread_rwlock_rdlock.c 
b/libs/libc/pthread/pthread_rwlock_rdlock.c
index 50f9b3ca5f2..7d87d8667d4 100644
--- a/libs/libc/pthread/pthread_rwlock_rdlock.c
+++ b/libs/libc/pthread/pthread_rwlock_rdlock.c
@@ -35,12 +35,14 @@
  * Private Functions
  ****************************************************************************/
 
+#if CONFIG_TLS_NCLEANUP > 0
 static void rdlock_cleanup(FAR void *arg)
 {
   FAR pthread_rwlock_t *rw_lock = (FAR pthread_rwlock_t *)arg;
 
   pthread_mutex_unlock(&rw_lock->lock);
 }
+#endif
 
 static int tryrdlock(FAR pthread_rwlock_t *rw_lock)
 {
@@ -109,7 +111,9 @@ int pthread_rwlock_clockrdlock(FAR pthread_rwlock_t 
*rw_lock,
       return err;
     }
 
+#if CONFIG_TLS_NCLEANUP > 0
   pthread_cleanup_push(&rdlock_cleanup, rw_lock);
+#endif
   while ((err = tryrdlock(rw_lock)) == EBUSY)
     {
       if (ts != NULL)
@@ -128,7 +132,9 @@ int pthread_rwlock_clockrdlock(FAR pthread_rwlock_t 
*rw_lock,
         }
     }
 
+#if CONFIG_TLS_NCLEANUP > 0
   pthread_cleanup_pop(0);
+#endif
 
   pthread_mutex_unlock(&rw_lock->lock);
   return err;
diff --git a/libs/libc/pthread/pthread_rwlock_wrlock.c 
b/libs/libc/pthread/pthread_rwlock_wrlock.c
index 02ec9f9547d..43ef48c5ebc 100644
--- a/libs/libc/pthread/pthread_rwlock_wrlock.c
+++ b/libs/libc/pthread/pthread_rwlock_wrlock.c
@@ -35,6 +35,7 @@
  * Private Functions
  ****************************************************************************/
 
+#if CONFIG_TLS_NCLEANUP > 0
 static void wrlock_cleanup(FAR void *arg)
 {
   FAR pthread_rwlock_t *rw_lock = (FAR pthread_rwlock_t *)arg;
@@ -42,6 +43,7 @@ static void wrlock_cleanup(FAR void *arg)
   rw_lock->num_writers--;
   pthread_mutex_unlock(&rw_lock->lock);
 }
+#endif
 
 /****************************************************************************
  * Public Functions
@@ -104,7 +106,9 @@ int pthread_rwlock_clockwrlock(FAR pthread_rwlock_t 
*rw_lock,
 
   rw_lock->num_writers++;
 
+#if CONFIG_TLS_NCLEANUP > 0
   pthread_cleanup_push(&wrlock_cleanup, rw_lock);
+#endif
   while (rw_lock->write_in_progress || rw_lock->num_readers > 0)
     {
       if (ts != NULL)
@@ -123,7 +127,9 @@ int pthread_rwlock_clockwrlock(FAR pthread_rwlock_t 
*rw_lock,
         }
     }
 
+#if CONFIG_TLS_NCLEANUP > 0
   pthread_cleanup_pop(0);
+#endif
 
   if (err == 0)
     {
diff --git a/libs/libc/tls/Kconfig b/libs/libc/tls/Kconfig
index cd34a4e366d..69b8866af1b 100644
--- a/libs/libc/tls/Kconfig
+++ b/libs/libc/tls/Kconfig
@@ -76,5 +76,8 @@ config TLS_NCLEANUP
                POSIX pthread cancellation.  The number of cleanup stack levels
                is the maximum number of pthread_cleanup_push() calls that can
                be made without a corresponding pthread_cleanup_pop() call.
+               With 0, pthread_cleanup_push() and pthread_cleanup_pop() do not
+               exist and a program that calls them does not link.  Each level
+               costs two pointers in every thread.
 
 endmenu # Thread Local Storage (TLS)

Reply via email to