nptl: Use pthread_kill on pthread_cancel

It consolidates the tgkill call and it is the first step of making
pthread_cancel async-signal-safe.  It also fix a possible issue
where the 'struct pthread' tid is not read atomically, which might
send an invalid cancellation signal (similar to what
db988e50a8 fixed for pthread_join).

Checked on x86_64-linux-gnu and aarch64-linux-gnu.
This commit is contained in:
Adhemerval Zanella 2020-12-07 17:17:24 -03:00
parent f779b1efb3
commit a6c813d0ad
3 changed files with 15 additions and 11 deletions

View File

@ -515,6 +515,8 @@ libc_hidden_proto (__pthread_detach)
extern int __pthread_kill (pthread_t threadid, int signo);
libc_hidden_proto (__pthread_kill)
extern int __pthread_cancel (pthread_t th);
extern int __pthread_kill_internal (pthread_t threadid, int signo)
attribute_hidden;
extern void __pthread_exit (void *value) __attribute__ ((__noreturn__));
libc_hidden_proto (__pthread_exit)
extern int __pthread_join (pthread_t threadid, void **thread_return);

View File

@ -110,11 +110,7 @@ __pthread_cancel (pthread_t th)
return 0;
}
pid_t pid = __getpid ();
int val = INTERNAL_SYSCALL_CALL (tgkill, pid, pd->tid, SIGCANCEL);
return INTERNAL_SYSCALL_ERROR_P (val)
? INTERNAL_SYSCALL_ERRNO (val)
: 0;
return __pthread_kill_internal (th, SIGCANCEL);
}
versioned_symbol (libc, __pthread_cancel, pthread_cancel, GLIBC_2_34);

View File

@ -21,13 +21,8 @@
#include <shlib-compat.h>
int
__pthread_kill (pthread_t threadid, int signo)
__pthread_kill_internal (pthread_t threadid, int signo)
{
/* Disallow sending the signal we use for cancellation, timers,
for the setxid implementation. */
if (__is_internal_signal (signo))
return EINVAL;
pid_t tid;
struct pthread *pd = (struct pthread *) threadid;
@ -55,6 +50,17 @@ __pthread_kill (pthread_t threadid, int signo)
return val;
}
int
__pthread_kill (pthread_t threadid, int signo)
{
/* Disallow sending the signal we use for cancellation, timers,
for the setxid implementation. */
if (__is_internal_signal (signo))
return EINVAL;
return __pthread_kill_internal (threadid, signo);
}
/* 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)