mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
Refactor Linux raise implementation (BZ#15368)
This patch changes both the nptl and libc Linux raise implementation to avoid the issues described in BZ#15368. The strategy used is summarized in bug report first comment: 1. Block all signals (including internal NPTL ones); 2. Get pid and tid directly from syscall (not relying on cached values); 3. Call tgkill; 4. Restore old signal mask. Tested on x86_64 and i686. [BZ #15368] * sysdeps/unix/sysv/linux/nptl-signals.h (__nptl_clear_internal_signals): New function. (__libc_signal_block_all): Likewise. (__libc_signal_block_app): Likewise. (__libc_signal_restore_set): Likewise. * sysdeps/unix/sysv/linux/pt-raise.c (raise): Use Linux raise.c implementation. * sysdeps/unix/sysv/linux/raise.c (raise): Reimplement to not use the cached pid/tid value in pthread structure.
This commit is contained in:
committed by
Adhemerval Zanella
parent
e15eaa8f33
commit
2ac88eecc5
@ -39,5 +39,46 @@ __nptl_is_internal_signal (int sig)
|
||||
return (sig == SIGCANCEL) || (sig == SIGTIMER) || (sig == SIGSETXID);
|
||||
}
|
||||
|
||||
/* Remove internal glibc signal from the mask. */
|
||||
static inline void
|
||||
__nptl_clear_internal_signals (sigset_t *set)
|
||||
{
|
||||
__sigdelset (set, SIGCANCEL);
|
||||
__sigdelset (set, SIGTIMER);
|
||||
__sigdelset (set, SIGSETXID);
|
||||
}
|
||||
|
||||
#define SIGALL_SET \
|
||||
((__sigset_t) { .__val = {[0 ... _SIGSET_NWORDS-1 ] = -1 } })
|
||||
|
||||
/* Block all signals, including internal glibc ones. */
|
||||
static inline int
|
||||
__libc_signal_block_all (sigset_t *set)
|
||||
{
|
||||
INTERNAL_SYSCALL_DECL (err);
|
||||
return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_BLOCK, &SIGALL_SET,
|
||||
set, _NSIG / 8);
|
||||
}
|
||||
|
||||
/* Block all application signals (excluding internal glibc ones). */
|
||||
static inline int
|
||||
__libc_signal_block_app (sigset_t *set)
|
||||
{
|
||||
sigset_t allset = SIGALL_SET;
|
||||
__nptl_clear_internal_signals (&allset);
|
||||
INTERNAL_SYSCALL_DECL (err);
|
||||
return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_BLOCK, &allset, set,
|
||||
_NSIG / 8);
|
||||
}
|
||||
|
||||
/* Restore current process signal mask. */
|
||||
static inline int
|
||||
__libc_signal_restore_set (const sigset_t *set)
|
||||
{
|
||||
INTERNAL_SYSCALL_DECL (err);
|
||||
return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, set, NULL,
|
||||
_NSIG / 8);
|
||||
}
|
||||
|
||||
/* Used to communicate with signal handler. */
|
||||
extern struct xid_command *__xidcmd attribute_hidden;
|
||||
|
Reference in New Issue
Block a user