diff options
Diffstat (limited to 'nptl/pthread_kill.c')
-rw-r--r-- | nptl/pthread_kill.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/nptl/pthread_kill.c b/nptl/pthread_kill.c index ad7e011..8982011 100644 --- a/nptl/pthread_kill.c +++ b/nptl/pthread_kill.c @@ -28,24 +28,40 @@ __pthread_kill (pthread_t threadid, int signo) if (__is_internal_signal (signo)) return EINVAL; - /* 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; struct pthread *pd = (struct pthread *) threadid; - pid_t tid = atomic_forced_read (pd->tid); - if (__glibc_unlikely (tid <= 0)) - /* Not a valid thread handle. */ - return ESRCH; - /* We have a special syscall to do the work. */ - pid_t pid = __getpid (); + if (pd == THREAD_SELF) + /* It is a special case to handle raise() implementation after a vfork + call (which does not update the PD tid field). */ + tid = INLINE_SYSCALL_CALL (gettid); + else + /* 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. */ + tid = atomic_forced_read (pd->tid); - int val = INTERNAL_SYSCALL_CALL (tgkill, pid, tid, signo); - return (INTERNAL_SYSCALL_ERROR_P (val) - ? INTERNAL_SYSCALL_ERRNO (val) : 0); + int val; + if (__glibc_likely (tid > 0)) + { + pid_t pid = __getpid (); + + val = INTERNAL_SYSCALL_CALL (tgkill, pid, tid, signo); + val = (INTERNAL_SYSCALL_ERROR_P (val) + ? INTERNAL_SYSCALL_ERRNO (val) : 0); + } + else + val = ESRCH; + + return val; } +/* Some architectures (for instance arm) might pull raise through libgcc, so + avoid the symbol version if it ends up being used on ld.so. */ +#if !IS_IN(rtld) +libc_hidden_def (__pthread_kill) versioned_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_34); -#if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) +# if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) compat_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_0); +# endif #endif |