From 345295c0d970158ea1f36832cbb424106b6a05bd Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Thu, 9 Sep 2021 16:24:08 -0300 Subject: [PATCH] nptl: Use exit_lock when accessing TID on pthread_getschedparam The sched_getparam call is also replaced with a INTERNAL_SYSCALL_CALL to avoid clobbering errno. Also return EINVAL if the thread is already terminated at the time of the call. Checked on x86_64-linux-gnu. --- nptl/pthread_getschedparam.c | 55 +++++++++++++++------------- sysdeps/pthread/tst-pthread-exited.c | 7 ++++ 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/nptl/pthread_getschedparam.c b/nptl/pthread_getschedparam.c index bb74ed959c..90e8026f95 100644 --- a/nptl/pthread_getschedparam.c +++ b/nptl/pthread_getschedparam.c @@ -15,24 +15,14 @@ License along with the GNU C Library; if not, see . */ -#include -#include -#include "pthreadP.h" -#include +#include +#include +#include - -int -__pthread_getschedparam (pthread_t threadid, int *policy, - struct sched_param *param) +static int +getschedparam (struct pthread *pd, int *policy, struct sched_param *param) { - struct pthread *pd = (struct pthread *) threadid; - - /* Make sure the descriptor is valid. */ - if (INVALID_TD_P (pd)) - /* Not a valid thread handle. */ - return ESRCH; - - int result = 0; + int r = 0; /* See CREATE THREAD NOTES in nptl/pthread_create.c. */ lll_lock (pd->lock, LLL_PRIVATE); @@ -44,22 +34,18 @@ __pthread_getschedparam (pthread_t threadid, int *policy, not yet been retrieved do it now. */ if ((pd->flags & ATTR_FLAG_SCHED_SET) == 0) { - if (__sched_getparam (pd->tid, &pd->schedparam) != 0) - result = 1; - else + r = INTERNAL_SYSCALL_CALL (sched_getparam, pd->tid, &pd->schedparam); + if (r == 0) pd->flags |= ATTR_FLAG_SCHED_SET; } - if ((pd->flags & ATTR_FLAG_POLICY_SET) == 0) { - pd->schedpolicy = __sched_getscheduler (pd->tid); - if (pd->schedpolicy == -1) - result = 1; - else + r = pd->schedpolicy = INTERNAL_SYSCALL_CALL (sched_getscheduler, pd->tid); + if (r >= 0) pd->flags |= ATTR_FLAG_POLICY_SET; } - if (result == 0) + if (r >= 0) { *policy = pd->schedpolicy; memcpy (param, &pd->schedparam, sizeof (struct sched_param)); @@ -67,6 +53,25 @@ __pthread_getschedparam (pthread_t threadid, int *policy, lll_unlock (pd->lock, LLL_PRIVATE); + return -r; +} + +int +__pthread_getschedparam (pthread_t threadid, int *policy, + struct sched_param *param) +{ + struct pthread *pd = (struct pthread *) threadid; + + /* Block all signals, as required by pd->exit_lock. */ + internal_sigset_t old_mask; + internal_signal_block_all (&old_mask); + __libc_lock_lock (pd->exit_lock); + + int result = pd->tid != 0 ? getschedparam (pd, policy, param) : EINVAL; + + __libc_lock_unlock (pd->exit_lock); + internal_signal_restore_set (&old_mask); + return result; } libc_hidden_def (__pthread_getschedparam) diff --git a/sysdeps/pthread/tst-pthread-exited.c b/sysdeps/pthread/tst-pthread-exited.c index b768685771..91c6533235 100644 --- a/sysdeps/pthread/tst-pthread-exited.c +++ b/sysdeps/pthread/tst-pthread-exited.c @@ -56,6 +56,13 @@ do_test (void) TEST_COMPARE (r, EINVAL); } + { + struct sched_param sch; + int policy; + int r = pthread_getschedparam (thr, &policy, &sch); + TEST_COMPARE (r, EINVAL); + } + xpthread_join (thr); return 0; -- 2.47.2