aboutsummaryrefslogtreecommitdiff
path: root/nptl
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2020-12-07 17:17:24 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2021-06-09 15:16:45 -0300
commita6c813d0ad0fd9830f2cd3c3d079af8d2aa50a1f (patch)
tree4a76233e9a815b23428b380ec689491ec9b8f7b4 /nptl
parentf779b1efb35fe141e47952af3ac7f0540acca401 (diff)
downloadglibc-a6c813d0ad0fd9830f2cd3c3d079af8d2aa50a1f.zip
glibc-a6c813d0ad0fd9830f2cd3c3d079af8d2aa50a1f.tar.gz
glibc-a6c813d0ad0fd9830f2cd3c3d079af8d2aa50a1f.tar.bz2
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 db988e50a87f613cb6b9e98a2fc66a4848bc3546 fixed for pthread_join). Checked on x86_64-linux-gnu and aarch64-linux-gnu.
Diffstat (limited to 'nptl')
-rw-r--r--nptl/pthreadP.h2
-rw-r--r--nptl/pthread_cancel.c6
-rw-r--r--nptl/pthread_kill.c18
3 files changed, 15 insertions, 11 deletions
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index 618922f..675d1de 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -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);
diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c
index de4659a..0698cd2 100644
--- a/nptl/pthread_cancel.c
+++ b/nptl/pthread_cancel.c
@@ -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);
diff --git a/nptl/pthread_kill.c b/nptl/pthread_kill.c
index 8982011..f79a2b2 100644
--- a/nptl/pthread_kill.c
+++ b/nptl/pthread_kill.c
@@ -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)