diff options
-rw-r--r-- | nptl/pthread_sigqueue.c | 42 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/pthread_sigqueue.c | 71 |
2 files changed, 38 insertions, 75 deletions
diff --git a/nptl/pthread_sigqueue.c b/nptl/pthread_sigqueue.c index 7d60e2b98d..64bacfe41b 100644 --- a/nptl/pthread_sigqueue.c +++ b/nptl/pthread_sigqueue.c @@ -1,6 +1,6 @@ -/* Queue a signal (with value) for a specific pthread. Stub version. - Copyright (C) 2014-2021 Free Software Foundation, Inc. +/* Copyright (C) 2009-2021 Free Software Foundation, Inc. This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2009. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -18,12 +18,17 @@ #include <errno.h> #include <signal.h> +#include <string.h> +#include <unistd.h> #include <pthreadP.h> +#include <tls.h> +#include <sysdep.h> int pthread_sigqueue (pthread_t threadid, int signo, const union sigval value) { +#ifdef __NR_rt_tgsigqueueinfo struct pthread *pd = (struct pthread *) threadid; /* Make sure the descriptor is valid. */ @@ -31,7 +36,36 @@ pthread_sigqueue (pthread_t threadid, int signo, const union sigval value) /* Not a valid thread handle. */ return ESRCH; + /* Force load of pd->tid into local variable or register. Otherwise + if a thread exits between ESRCH test and tgkill, we might return + EINVAL, because pd->tid would be cleared by the kernel. */ + pid_t tid = atomic_forced_read (pd->tid); + if (__glibc_unlikely (tid <= 0)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Disallow sending the signal we use for cancellation, timers, + for the setxid implementation. */ + if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID) + return EINVAL; + + pid_t pid = getpid (); + + /* Set up the siginfo_t structure. */ + siginfo_t info; + memset (&info, '\0', sizeof (siginfo_t)); + info.si_signo = signo; + info.si_code = SI_QUEUE; + info.si_pid = pid; + info.si_uid = getuid (); + info.si_value = value; + + /* We have a special syscall to do the work. */ + int val = INTERNAL_SYSCALL_CALL (rt_tgsigqueueinfo, pid, tid, signo, + &info); + return (INTERNAL_SYSCALL_ERROR_P (val) + ? INTERNAL_SYSCALL_ERRNO (val) : 0); +#else return ENOSYS; +#endif } - -stub_warning (pthread_sigqueue) diff --git a/sysdeps/unix/sysv/linux/pthread_sigqueue.c b/sysdeps/unix/sysv/linux/pthread_sigqueue.c deleted file mode 100644 index 64bacfe41b..0000000000 --- a/sysdeps/unix/sysv/linux/pthread_sigqueue.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (C) 2009-2021 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@redhat.com>, 2009. - - 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 <string.h> -#include <unistd.h> -#include <pthreadP.h> -#include <tls.h> -#include <sysdep.h> - - -int -pthread_sigqueue (pthread_t threadid, int signo, const union sigval value) -{ -#ifdef __NR_rt_tgsigqueueinfo - struct pthread *pd = (struct pthread *) threadid; - - /* Make sure the descriptor is valid. */ - if (DEBUGGING_P && INVALID_TD_P (pd)) - /* Not a valid thread handle. */ - return ESRCH; - - /* Force load of pd->tid into local variable or register. Otherwise - if a thread exits between ESRCH test and tgkill, we might return - EINVAL, because pd->tid would be cleared by the kernel. */ - pid_t tid = atomic_forced_read (pd->tid); - if (__glibc_unlikely (tid <= 0)) - /* Not a valid thread handle. */ - return ESRCH; - - /* Disallow sending the signal we use for cancellation, timers, - for the setxid implementation. */ - if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID) - return EINVAL; - - pid_t pid = getpid (); - - /* Set up the siginfo_t structure. */ - siginfo_t info; - memset (&info, '\0', sizeof (siginfo_t)); - info.si_signo = signo; - info.si_code = SI_QUEUE; - info.si_pid = pid; - info.si_uid = getuid (); - info.si_value = value; - - /* We have a special syscall to do the work. */ - int val = INTERNAL_SYSCALL_CALL (rt_tgsigqueueinfo, pid, tid, signo, - &info); - return (INTERNAL_SYSCALL_ERROR_P (val) - ? INTERNAL_SYSCALL_ERRNO (val) : 0); -#else - return ENOSYS; -#endif -} |