mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-25 06:20:06 +00:00
nptl: Install cancellation handler on pthread_cancel
Now that cancellation is not used anymore to handle thread setup creation failure, the sighandle can be installed only when pthread_cancel is actually used. Checked on x86_64-linux-gnu and aarch64-linux-gnu.
This commit is contained in:
parent
02189e8fb0
commit
41c7295617
@ -403,7 +403,6 @@ libc {
|
|||||||
__nptl_free_tcb;
|
__nptl_free_tcb;
|
||||||
__nptl_nthreads;
|
__nptl_nthreads;
|
||||||
__nptl_setxid_sighandler;
|
__nptl_setxid_sighandler;
|
||||||
__nptl_sigcancel_handler;
|
|
||||||
__nptl_stack_list_add;
|
__nptl_stack_list_add;
|
||||||
__nptl_stack_list_del;
|
__nptl_stack_list_del;
|
||||||
__pthread_attr_copy;
|
__pthread_attr_copy;
|
||||||
@ -522,4 +521,4 @@ ld {
|
|||||||
__nptl_initial_report_events;
|
__nptl_initial_report_events;
|
||||||
__nptl_set_robust_list_avail;
|
__nptl_set_robust_list_avail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -569,12 +569,6 @@ libc_hidden_proto (__pthread_attr_setsigmask_internal)
|
|||||||
extern __typeof (pthread_attr_getsigmask_np) __pthread_attr_getsigmask_np;
|
extern __typeof (pthread_attr_getsigmask_np) __pthread_attr_getsigmask_np;
|
||||||
libc_hidden_proto (__pthread_attr_getsigmask_np)
|
libc_hidden_proto (__pthread_attr_getsigmask_np)
|
||||||
|
|
||||||
/* The cancellation signal handler defined alongside with
|
|
||||||
pthread_cancel. This is included in statically linked binaries
|
|
||||||
only if pthread_cancel is linked in. */
|
|
||||||
void __nptl_sigcancel_handler (int sig, siginfo_t *si, void *ctx);
|
|
||||||
libc_hidden_proto (__nptl_sigcancel_handler)
|
|
||||||
|
|
||||||
/* Special versions which use non-exported functions. */
|
/* Special versions which use non-exported functions. */
|
||||||
extern void __pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
|
extern void __pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
|
||||||
void (*routine) (void *), void *arg);
|
void (*routine) (void *), void *arg);
|
||||||
|
@ -28,11 +28,19 @@
|
|||||||
#include <gnu/lib-names.h>
|
#include <gnu/lib-names.h>
|
||||||
#include <sys/single_threaded.h>
|
#include <sys/single_threaded.h>
|
||||||
|
|
||||||
/* For asynchronous cancellation we use a signal. This is the core
|
/* For asynchronous cancellation we use a signal. */
|
||||||
logic of the signal handler. */
|
|
||||||
static void
|
static void
|
||||||
sigcancel_handler (void)
|
sigcancel_handler (int sig, siginfo_t *si, void *ctx)
|
||||||
{
|
{
|
||||||
|
/* Safety check. It would be possible to call this function for
|
||||||
|
other signals and send a signal from another process. This is not
|
||||||
|
correct and might even be a security problem. Try to catch as
|
||||||
|
many incorrect invocations as possible. */
|
||||||
|
if (sig != SIGCANCEL
|
||||||
|
|| si->si_pid != __getpid()
|
||||||
|
|| si->si_code != SI_TKILL)
|
||||||
|
return;
|
||||||
|
|
||||||
struct pthread *self = THREAD_SELF;
|
struct pthread *self = THREAD_SELF;
|
||||||
|
|
||||||
int oldval = THREAD_GETMEM (self, cancelhandling);
|
int oldval = THREAD_GETMEM (self, cancelhandling);
|
||||||
@ -66,24 +74,6 @@ sigcancel_handler (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is the actually installed SIGCANCEL handler. It adds some
|
|
||||||
safety checks before performing the cancellation. */
|
|
||||||
void
|
|
||||||
__nptl_sigcancel_handler (int sig, siginfo_t *si, void *ctx)
|
|
||||||
{
|
|
||||||
/* Safety check. It would be possible to call this function for
|
|
||||||
other signals and send a signal from another process. This is not
|
|
||||||
correct and might even be a security problem. Try to catch as
|
|
||||||
many incorrect invocations as possible. */
|
|
||||||
if (sig != SIGCANCEL
|
|
||||||
|| si->si_pid != __getpid()
|
|
||||||
|| si->si_code != SI_TKILL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sigcancel_handler ();
|
|
||||||
}
|
|
||||||
libc_hidden_def (__nptl_sigcancel_handler)
|
|
||||||
|
|
||||||
int
|
int
|
||||||
__pthread_cancel (pthread_t th)
|
__pthread_cancel (pthread_t th)
|
||||||
{
|
{
|
||||||
@ -94,6 +84,17 @@ __pthread_cancel (pthread_t th)
|
|||||||
/* Not a valid thread handle. */
|
/* Not a valid thread handle. */
|
||||||
return ESRCH;
|
return ESRCH;
|
||||||
|
|
||||||
|
static int init_sigcancel = 0;
|
||||||
|
if (atomic_load_relaxed (&init_sigcancel) == 0)
|
||||||
|
{
|
||||||
|
struct sigaction sa;
|
||||||
|
sa.sa_sigaction = sigcancel_handler;
|
||||||
|
sa.sa_flags = SA_SIGINFO;
|
||||||
|
__sigemptyset (&sa.sa_mask);
|
||||||
|
__libc_sigaction (SIGCANCEL, &sa, NULL);
|
||||||
|
atomic_store_relaxed (&init_sigcancel, 1);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef SHARED
|
#ifdef SHARED
|
||||||
/* Trigger an error if libgcc_s cannot be loaded. */
|
/* Trigger an error if libgcc_s cannot be loaded. */
|
||||||
{
|
{
|
||||||
@ -134,7 +135,11 @@ __pthread_cancel (pthread_t th)
|
|||||||
call pthread_cancel (pthread_self ()) without calling
|
call pthread_cancel (pthread_self ()) without calling
|
||||||
pthread_create, so the signal handler may not have been
|
pthread_create, so the signal handler may not have been
|
||||||
set up for a self-cancel. */
|
set up for a self-cancel. */
|
||||||
sigcancel_handler ();
|
{
|
||||||
|
THREAD_SETMEM (pd, result, PTHREAD_CANCELED);
|
||||||
|
if ((newval & CANCELTYPE_BITMASK) != 0)
|
||||||
|
__do_cancel ();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* The cancellation handler will take care of marking the
|
/* The cancellation handler will take care of marking the
|
||||||
|
@ -67,21 +67,6 @@ late_init (void)
|
|||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
__sigemptyset (&sa.sa_mask);
|
__sigemptyset (&sa.sa_mask);
|
||||||
|
|
||||||
/* Install the cancellation signal handler (in static builds only if
|
|
||||||
pthread_cancel has been linked in). If for some reason we cannot
|
|
||||||
install the handler we do not abort. Maybe we should, but it is
|
|
||||||
only asynchronous cancellation which is affected. */
|
|
||||||
#ifndef SHARED
|
|
||||||
extern __typeof (__nptl_sigcancel_handler) __nptl_sigcancel_handler
|
|
||||||
__attribute__ ((weak));
|
|
||||||
if (__nptl_sigcancel_handler != NULL)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
sa.sa_sigaction = __nptl_sigcancel_handler;
|
|
||||||
sa.sa_flags = SA_SIGINFO;
|
|
||||||
(void) __libc_sigaction (SIGCANCEL, &sa, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Install the handle to change the threads' uid/gid. Use
|
/* Install the handle to change the threads' uid/gid. Use
|
||||||
SA_ONSTACK because the signal may be sent to threads that are
|
SA_ONSTACK because the signal may be sent to threads that are
|
||||||
running with custom stacks. (This is less likely for
|
running with custom stacks. (This is less likely for
|
||||||
|
Loading…
Reference in New Issue
Block a user