1 /* Copyright (C) 2002-2021 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
25 #include <unwind-link.h>
27 #include <gnu/lib-names.h>
28 #include <sys/single_threaded.h>
30 /* For asynchronous cancellation we use a signal. */
32 sigcancel_handler (int sig
, siginfo_t
*si
, void *ctx
)
34 /* Safety check. It would be possible to call this function for
35 other signals and send a signal from another process. This is not
36 correct and might even be a security problem. Try to catch as
37 many incorrect invocations as possible. */
39 || si
->si_pid
!= __getpid()
40 || si
->si_code
!= SI_TKILL
)
43 struct pthread
*self
= THREAD_SELF
;
45 int ch
= atomic_load_relaxed (&self
->cancelhandling
);
46 /* Cancelation not enabled, not cancelled, or already exitting. */
47 if (self
->cancelstate
== PTHREAD_CANCEL_DISABLE
48 || (ch
& CANCELED_BITMASK
) == 0
49 || (ch
& EXITING_BITMASK
) != 0)
52 /* Set the return value. */
53 THREAD_SETMEM (self
, result
, PTHREAD_CANCELED
);
54 /* Make sure asynchronous cancellation is still enabled. */
55 if (self
->canceltype
== PTHREAD_CANCEL_ASYNCHRONOUS
)
60 __pthread_cancel (pthread_t th
)
62 volatile struct pthread
*pd
= (volatile struct pthread
*) th
;
65 /* The thread has already exited on the kernel side. Its outcome
66 (regular exit, other cancelation) has already been
70 static int init_sigcancel
= 0;
71 if (atomic_load_relaxed (&init_sigcancel
) == 0)
74 sa
.sa_sigaction
= sigcancel_handler
;
75 /* The signal handle should be non-interruptible to avoid the risk of
76 spurious EINTR caused by SIGCANCEL sent to process or if
77 pthread_cancel() is called while cancellation is disabled in the
79 sa
.sa_flags
= SA_SIGINFO
| SA_RESTART
;
80 __sigemptyset (&sa
.sa_mask
);
81 __libc_sigaction (SIGCANCEL
, &sa
, NULL
);
82 atomic_store_relaxed (&init_sigcancel
, 1);
86 /* Trigger an error if libgcc_s cannot be loaded. */
88 struct unwind_link
*unwind_link
= __libc_unwind_link_get ();
89 if (unwind_link
== NULL
)
90 __libc_fatal (LIBGCC_S_SO
91 " must be installed for pthread_cancel to work\n");
95 int oldch
= atomic_fetch_or_acquire (&pd
->cancelhandling
, CANCELED_BITMASK
);
96 if ((oldch
& CANCELED_BITMASK
) != 0)
99 if (pd
== THREAD_SELF
)
101 /* A single-threaded process should be able to kill itself, since there
102 is nothing in the POSIX specification that says that it cannot. So
103 we set multiple_threads to true so that cancellation points get
105 THREAD_SETMEM (THREAD_SELF
, header
.multiple_threads
, 1);
106 #ifndef TLS_MULTIPLE_THREADS_IN_TCB
107 __libc_multiple_threads
= 1;
110 THREAD_SETMEM (pd
, result
, PTHREAD_CANCELED
);
111 if (pd
->cancelstate
== PTHREAD_CANCEL_ENABLE
112 && pd
->canceltype
== PTHREAD_CANCEL_ASYNCHRONOUS
)
117 return __pthread_kill_internal (th
, SIGCANCEL
);
119 versioned_symbol (libc
, __pthread_cancel
, pthread_cancel
, GLIBC_2_34
);
121 #if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34)
122 compat_symbol (libpthread
, __pthread_cancel
, pthread_cancel
, GLIBC_2_0
);
125 /* Ensure that the unwinder is always linked in (the __pthread_unwind
126 reference from __do_cancel is weak). Use ___pthread_unwind_next
127 (three underscores) to produce a strong reference to the same
129 PTHREAD_STATIC_FN_REQUIRE (___pthread_unwind_next
)