]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
nptl: Remove INVALID_TD_P
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Thu, 11 Dec 2025 20:47:20 +0000 (17:47 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Fri, 19 Dec 2025 16:23:06 +0000 (13:23 -0300)
And use the new __pthread_descriptor_valid function that checks
for 'joinstate' to get the thread state instead of 'tid'.  The
joinstate is set by the kernel when the thread exits.

Checked on x86_64-linux-gnu.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
nptl/pthread_getcpuclockid.c
nptl/pthread_getschedparam.c
nptl/pthread_setschedparam.c
nptl/pthread_setschedprio.c
sysdeps/nptl/pthreadP.h
sysdeps/pthread/Makefile
sysdeps/pthread/tst-pthread-exited.c [new file with mode: 0644]

index 0cd9f77bea2bf1d05e84a3d09d279356096a5d59..70677d01381f49d6787a55fcd255162855b156fb 100644 (file)
@@ -29,7 +29,7 @@ __pthread_getcpuclockid (pthread_t threadid, clockid_t *clockid)
   struct pthread *pd = (struct pthread *) threadid;
 
   /* Make sure the descriptor is valid.  */
-  if (INVALID_TD_P (pd))
+  if (!__pthread_descriptor_valid (pd))
     /* Not a valid thread handle.  */
     return ESRCH;
 
index bb74ed959c82a559e90ec1fc726131d5233cd338..aab0d836ced4fcc4e3c5a8f48fa10d8d61f9ed59 100644 (file)
@@ -28,7 +28,7 @@ __pthread_getschedparam (pthread_t threadid, int *policy,
   struct pthread *pd = (struct pthread *) threadid;
 
   /* Make sure the descriptor is valid.  */
-  if (INVALID_TD_P (pd))
+  if (!__pthread_descriptor_valid (pd))
     /* Not a valid thread handle.  */
     return ESRCH;
 
index 1b43eb1f714be4e44663c36997ea9cda9184fcdb..b057f8228ff679ab79ca49b4748535be4c8aae1a 100644 (file)
@@ -29,7 +29,7 @@ __pthread_setschedparam (pthread_t threadid, int policy,
   struct pthread *pd = (struct pthread *) threadid;
 
   /* Make sure the descriptor is valid.  */
-  if (INVALID_TD_P (pd))
+  if (!__pthread_descriptor_valid (pd))
     /* Not a valid thread handle.  */
     return ESRCH;
 
index c355716593ca0c808f1a621e0b9244ca8afc47b4..8cf7f5380f5a3b14e97067263a64603cf5f47ba1 100644 (file)
@@ -29,7 +29,7 @@ __pthread_setschedprio (pthread_t threadid, int prio)
   struct pthread *pd = (struct pthread *) threadid;
 
   /* Make sure the descriptor is valid.  */
-  if (INVALID_TD_P (pd))
+  if (!__pthread_descriptor_valid (pd))
     /* Not a valid thread handle.  */
     return ESRCH;
 
index 3f5f3887e9ed3155825d8079d4083700d2c62612..bc0f84d945033256f5308dab2ffb73a627fed6c9 100644 (file)
@@ -216,7 +216,11 @@ libc_hidden_proto (__pthread_current_priority)
 /* This will not catch all invalid descriptors but is better than
    nothing.  And if the test triggers the thread descriptor is
    guaranteed to be invalid.  */
-#define INVALID_TD_P(pd) __builtin_expect ((pd)->tid <= 0, 0)
+static inline bool
+__pthread_descriptor_valid (struct pthread *pd)
+{
+  return atomic_load_relaxed (&pd->joinstate) != THREAD_STATE_EXITED;
+}
 
 extern void __pthread_unwind (__pthread_unwind_buf_t *__buf)
      __cleanup_fct_attribute __attribute ((__noreturn__))
index c6ea59ee1654fe257445fa9c64b0a4341474f0f7..73bd5e6162496dbfb950ad30ea6c82405d9949ba 100644 (file)
@@ -212,6 +212,7 @@ tests += \
   tst-pt-vfork1 \
   tst-pt-vfork2 \
   tst-pthread-exit-signal \
+  tst-pthread-exited \
   tst-pthread-mutexattr \
   tst-pthread-mutexattr-2 \
   tst-pthread-raise-blocked-self \
diff --git a/sysdeps/pthread/tst-pthread-exited.c b/sysdeps/pthread/tst-pthread-exited.c
new file mode 100644 (file)
index 0000000..91c242c
--- /dev/null
@@ -0,0 +1,119 @@
+/* Test pthread interface which should return ESRCH when issued
+   with a terminated pthread_t.
+
+   Copyright (C) 2025 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <signal.h>
+#include <stddef.h>
+#include <grp.h>
+#include <pwd.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xthread.h>
+#include <unistd.h>
+
+static void *
+noop_thread (void *closure)
+{
+  return NULL;
+}
+
+enum { nthreads = 8 };
+
+static int
+do_test_default (void)
+{
+  pthread_t thrs[nthreads];
+  for (int i = 0; i < nthreads; i++)
+    thrs[i] = xpthread_create (NULL, noop_thread, NULL);
+
+  support_wait_for_thread_exit ();
+
+  for (int i = 0; i < nthreads; i++)
+    {
+      clockid_t clk;
+      TEST_COMPARE (pthread_getcpuclockid (thrs[i], &clk), ESRCH);
+
+      struct sched_param sch = { 0 };
+      int policy;
+      TEST_COMPARE (pthread_getschedparam (thrs[i], &policy, &sch), ESRCH);
+
+      TEST_COMPARE (pthread_setschedparam (thrs[i], SCHED_FIFO, &sch), ESRCH);
+
+      TEST_COMPARE (pthread_setschedprio (thrs[i], 0), ESRCH);
+    }
+
+  for (int i = 0; i < nthreads; i++)
+    xpthread_join (thrs[i]);
+
+  return 0;
+}
+
+
+static void *
+detached_pause_thread (void *closure)
+{
+  pthread_detach (pthread_self ());
+  pause ();
+  return NULL;
+}
+
+static void
+do_test_detached (void)
+{
+  pthread_t thrs[nthreads];
+  for (int i = 0; i < nthreads; i++)
+    thrs[i] = xpthread_create (NULL, detached_pause_thread, NULL);
+
+  for (int i = 0; i < nthreads; i++)
+    {
+      clockid_t clk;
+      TEST_COMPARE (pthread_getcpuclockid (thrs[i], &clk), 0);
+
+      struct sched_param sch = { 0 };
+      int policy;
+      TEST_COMPARE (pthread_getschedparam (thrs[i], &policy, &sch), 0);
+
+      sch.sched_priority = 8;
+      TEST_COMPARE (pthread_setschedparam (thrs[i], SCHED_FIFO, &sch), EPERM);
+
+      TEST_COMPARE (pthread_setschedprio (thrs[i], 0), 0);
+    }
+}
+
+static int
+do_test (void)
+{
+  /* The test relies on pthread setup failures that succeed as root.  */
+  if (geteuid () == 0)
+    {
+      struct passwd *pwd = getpwnam ("nobody");
+      if (pwd == NULL)
+       FAIL_UNSUPPORTED ("iuser nobody doesn't exist");
+
+      TEST_VERIFY_EXIT (setresuid (pwd->pw_uid, pwd->pw_uid, -1) == 0);
+    }
+
+  do_test_default ();
+  do_test_detached ();
+
+  return 0;
+}
+
+#include <support/test-driver.c>