1
0
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:
Adhemerval Zanella
2016-04-22 09:25:20 -03:00
committed by Adhemerval Zanella
parent e15eaa8f33
commit 2ac88eecc5
4 changed files with 88 additions and 48 deletions

View File

@ -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;