diff options
| author | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2025-03-12 10:59:17 -0300 |
|---|---|---|
| committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2025-03-13 09:11:13 -0300 |
| commit | 360cce0b066f34e85e473c04cdc16e6fa426021b (patch) | |
| tree | bc14d9e004fb398704a8b5a27d72fbe766461037 /nptl | |
| parent | dbc5a50d12eff4cb3f782129029d04b8a76f58e7 (diff) | |
| download | glibc-360cce0b066f34e85e473c04cdc16e6fa426021b.tar.xz glibc-360cce0b066f34e85e473c04cdc16e6fa426021b.zip | |
nptl: Check if thread is already terminated in sigcancel_handler (BZ 32782)
The SIGCANCEL signal handler should not issue __syscall_do_cancel,
which calls __do_cancel and __pthread_unwind, if the cancellation
is already in proces (and libgcc unwind is not reentrant). Any
cancellation signal received after is ignored.
Checked on x86_64-linux-gnu and aarch64-linux-gnu.
Tested-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
Diffstat (limited to 'nptl')
| -rw-r--r-- | nptl/pthread_cancel.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c index f7ce3ec51b..b838273881 100644 --- a/nptl/pthread_cancel.c +++ b/nptl/pthread_cancel.c @@ -41,15 +41,17 @@ sigcancel_handler (int sig, siginfo_t *si, void *ctx) || si->si_code != SI_TKILL) return; - /* Check if asynchronous cancellation mode is set or if interrupted - instruction pointer falls within the cancellable syscall bridge. For - interruptable syscalls with external side-effects (i.e. partial reads), - the kernel will set the IP to after __syscall_cancel_arch_end, thus - disabling the cancellation and allowing the process to handle such + /* Check if asynchronous cancellation mode is set and cancellation is not + already in progress, or if interrupted instruction pointer falls within + the cancellable syscall bridge. + For interruptable syscalls with external side-effects (i.e. partial + reads), the kernel will set the IP to after __syscall_cancel_arch_end, + thus disabling the cancellation and allowing the process to handle such conditions. */ struct pthread *self = THREAD_SELF; int oldval = atomic_load_relaxed (&self->cancelhandling); - if (cancel_async_enabled (oldval) || cancellation_pc_check (ctx)) + if (cancel_enabled_and_canceled_and_async (oldval) + || cancellation_pc_check (ctx)) __syscall_do_cancel (); } |
