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 /sysdeps | |
parent | dbc5a50d12eff4cb3f782129029d04b8a76f58e7 (diff) | |
download | glibc-360cce0b066f34e85e473c04cdc16e6fa426021b.zip glibc-360cce0b066f34e85e473c04cdc16e6fa426021b.tar.gz glibc-360cce0b066f34e85e473c04cdc16e6fa426021b.tar.bz2 |
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 'sysdeps')
-rw-r--r-- | sysdeps/pthread/Makefile | 1 | ||||
-rw-r--r-- | sysdeps/pthread/tst-cancel32.c | 73 |
2 files changed, 74 insertions, 0 deletions
diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile index 70e62b2..d4869c6 100644 --- a/sysdeps/pthread/Makefile +++ b/sysdeps/pthread/Makefile @@ -106,6 +106,7 @@ tests += \ tst-cancel28 \ tst-cancel29 \ tst-cancel30 \ + tst-cancel32 \ tst-cleanup0 \ tst-cleanup1 \ tst-cleanup2 \ diff --git a/sysdeps/pthread/tst-cancel32.c b/sysdeps/pthread/tst-cancel32.c new file mode 100644 index 0000000..ab550c1 --- /dev/null +++ b/sysdeps/pthread/tst-cancel32.c @@ -0,0 +1,73 @@ +/* Check if pthread_setcanceltype disables asynchronous cancellation + once cancellation happens (BZ 32782) + + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +/* The pthread_setcanceltype is a cancellation entrypoint, and if + asynchronous is enabled and the cancellation starts (on the second + pthread_setcanceltype call), the asynchronous should not restart + the process. */ + +#include <support/xthread.h> + +#define NITER 1000 +#define NTHREADS 8 + +static void +tf_cleanup (void *arg) +{ +} + +static void * +tf (void *closure) +{ + pthread_cleanup_push (tf_cleanup, NULL); + for (;;) + { + /* The only possible failure for pthread_setcanceltype is an + invalid state type. */ + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL); + } + pthread_cleanup_pop (1); + + return NULL; +} + +static void +poll_threads (int nthreads) +{ + pthread_t thr[nthreads]; + for (int i = 0; i < nthreads; i++) + thr[i] = xpthread_create (NULL, tf, NULL); + for (int i = 0; i < nthreads; i++) + xpthread_cancel (thr[i]); + for (int i = 0; i < nthreads; i++) + xpthread_join (thr[i]); +} + +static int +do_test (void) +{ + for (int k = 0; k < NITER; k++) + poll_threads (NTHREADS); + + return 0; +} + +#include <support/test-driver.c> |