aboutsummaryrefslogtreecommitdiff
path: root/nptl
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2025-03-12 10:59:17 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2025-03-13 09:11:13 -0300
commit360cce0b066f34e85e473c04cdc16e6fa426021b (patch)
treebc14d9e004fb398704a8b5a27d72fbe766461037 /nptl
parentdbc5a50d12eff4cb3f782129029d04b8a76f58e7 (diff)
downloadglibc-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.c14
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 ();
}