diff --git a/nptl/pthread_getcpuclockid.c b/nptl/pthread_getcpuclockid.c index 0cd9f77bea..70677d0138 100644 --- a/nptl/pthread_getcpuclockid.c +++ b/nptl/pthread_getcpuclockid.c @@ -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; diff --git a/nptl/pthread_getschedparam.c b/nptl/pthread_getschedparam.c index bb74ed959c..aab0d836ce 100644 --- a/nptl/pthread_getschedparam.c +++ b/nptl/pthread_getschedparam.c @@ -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; diff --git a/nptl/pthread_setschedparam.c b/nptl/pthread_setschedparam.c index 1b43eb1f71..b057f8228f 100644 --- a/nptl/pthread_setschedparam.c +++ b/nptl/pthread_setschedparam.c @@ -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; diff --git a/nptl/pthread_setschedprio.c b/nptl/pthread_setschedprio.c index c355716593..8cf7f5380f 100644 --- a/nptl/pthread_setschedprio.c +++ b/nptl/pthread_setschedprio.c @@ -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; diff --git a/sysdeps/nptl/pthreadP.h b/sysdeps/nptl/pthreadP.h index b6a6d8f18d..2ec0a3fe96 100644 --- a/sysdeps/nptl/pthreadP.h +++ b/sysdeps/nptl/pthreadP.h @@ -217,6 +217,11 @@ libc_hidden_proto (__pthread_current_priority) 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__)) diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile index c6ea59ee16..73bd5e6162 100644 --- a/sysdeps/pthread/Makefile +++ b/sysdeps/pthread/Makefile @@ -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 index 0000000000..a951d09040 --- /dev/null +++ b/sysdeps/pthread/tst-pthread-exited.c @@ -0,0 +1,106 @@ +/* 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 + . */ + +#include +#include +#include +#include +#include +#include + +static void * +noop_thread (void *closure) +{ + return NULL; +} + +enum { nthreads = 1 }; + +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) +{ + do_test_default (); + do_test_detached (); + + return 0; +} + +#include