Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient. In glibc, sigset_t is an array with space for 1024 bits, which is much more than required: all architectures supported by Linux have only 64 signals except MIPS, which has 128. In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than necessary. With this change, signal mask is decoded without use of intermediate sigset_t structure, which saves us some cpu cycles in case of glibc with its inflated sigset_t, and enables build with libcs where sigset_t is broken. Old implementation used to check each signal number in the given signal mask twice using sigismember(). New implementation is based on popcount and next_set_bit() so it's noticeably faster. * configure.ac: Check for __builtin_popcount. * signal.c: Ensure that NSIG >= 32. (sprintsigmask, sprintsigmask_long, printsigmask): Remove. (popcount32, sprintsigmask_n): New functions. (tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros. (print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask, sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use new signal mask decoding interface. * tests/sigaction.c (main): Add a test with almost filled signal mask. * tests/sigaction.awk: Update.
This commit is contained in:
parent
d354130b3a
commit
38593e942a
@ -309,6 +309,15 @@ if test "x$st_cv_sa_restorer" != xno; then
|
||||
[SA_RESTORER defined in <asm/signal.h>])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for __builtin_popcount], [st_cv_have___builtin_popcount],
|
||||
[AC_LINK_IFELSE([AC_LANG_PROGRAM([], [__builtin_popcount(0)])],
|
||||
[st_cv_have___builtin_popcount=yes],
|
||||
[st_cv_have___builtin_popcount=no])])
|
||||
if test "x$st_cv_have___builtin_popcount" = xyes; then
|
||||
AC_DEFINE([HAVE___BUILTIN_POPCOUNT], [1],
|
||||
[Define to 1 if the system provides __builtin_popcount function])
|
||||
fi
|
||||
|
||||
AC_PATH_PROG([PERL], [perl])
|
||||
|
||||
AC_CONFIG_FILES([Makefile tests/Makefile])
|
||||
|
210
signal.c
210
signal.c
@ -86,6 +86,8 @@ struct sigcontext {
|
||||
#ifndef NSIG
|
||||
# warning: NSIG is not defined, using 32
|
||||
# define NSIG 32
|
||||
#elif NSIG < 32
|
||||
# error: NSIG < 32
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
@ -211,64 +213,75 @@ signame(int sig)
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char *
|
||||
sprintsigmask(const char *str, sigset_t *mask)
|
||||
/* set might include realtime sigs */
|
||||
static unsigned int
|
||||
popcount32(const uint32_t *a, unsigned int size)
|
||||
{
|
||||
/* Was [8 * sizeof(sigset_t) * 8], but
|
||||
* glibc sigset_t is huge (1024 bits = 128 *bytes*),
|
||||
* and we were ending up with 8k (!) buffer here.
|
||||
*
|
||||
* No Unix system can have sig > 255
|
||||
* (waitpid API won't be able to indicate death from one)
|
||||
* and sig 0 doesn't exist either.
|
||||
* Therefore max possible no of sigs is 255: 1..255
|
||||
*/
|
||||
static char outstr[8 * (255 * 2 / 3)];
|
||||
unsigned int count = 0;
|
||||
|
||||
int i, nsigs;
|
||||
int maxsigs;
|
||||
int show_members;
|
||||
char sep;
|
||||
char *s;
|
||||
for (; size; ++a, --size) {
|
||||
uint32_t x = *a;
|
||||
|
||||
/* Note: nsignals = ARRAY_SIZE(signalent[]),
|
||||
* and that array may not have SIGRTnn.
|
||||
*/
|
||||
#ifdef __SIGRTMAX
|
||||
maxsigs = __SIGRTMAX + 1; /* instead */
|
||||
#ifdef HAVE___BUILTIN_POPCOUNT
|
||||
count += __builtin_popcount(x);
|
||||
#else
|
||||
maxsigs = nsignals;
|
||||
for (; x; ++count)
|
||||
x &= x - 1;
|
||||
#endif
|
||||
s = stpcpy(outstr, str);
|
||||
nsigs = 0;
|
||||
for (i = 1; i < maxsigs; i++) {
|
||||
if (sigismember(mask, i) == 1)
|
||||
nsigs++;
|
||||
}
|
||||
|
||||
/* 1: show mask members, 0: show those which are NOT in mask */
|
||||
show_members = (nsigs < nsignals * 2 / 3);
|
||||
if (!show_members)
|
||||
return count;
|
||||
}
|
||||
|
||||
static const char *
|
||||
sprintsigmask_n(const char *prefix, const void *sig_mask, unsigned int bytes)
|
||||
{
|
||||
/*
|
||||
* The maximum number of signal names to be printed is NSIG * 2 / 3.
|
||||
* Most of signal names have length 7,
|
||||
* average length of signal names is less than 7.
|
||||
* The length of prefix string does not exceed 16.
|
||||
*/
|
||||
static char outstr[128 + 8 * (NSIG * 2 / 3)];
|
||||
|
||||
char *s;
|
||||
const uint32_t *mask;
|
||||
uint32_t inverted_mask[NSIG / 32];
|
||||
unsigned int size;
|
||||
int i;
|
||||
char sep;
|
||||
|
||||
s = stpcpy(outstr, prefix);
|
||||
|
||||
mask = sig_mask;
|
||||
/* length of signal mask in 4-byte words */
|
||||
size = (bytes >= NSIG / 8) ? NSIG / 32 : (bytes + 3) / 4;
|
||||
|
||||
/* check whether 2/3 or more bits are set */
|
||||
if (popcount32(mask, size) >= size * 32 * 2 / 3) {
|
||||
/* show those signals that are NOT in the mask */
|
||||
unsigned int j;
|
||||
for (j = 0; j < size; ++j)
|
||||
inverted_mask[j] = ~mask[j];
|
||||
mask = inverted_mask;
|
||||
*s++ = '~';
|
||||
}
|
||||
|
||||
sep = '[';
|
||||
for (i = 1; i < maxsigs; i++) {
|
||||
if (sigismember(mask, i) == show_members) {
|
||||
*s++ = sep;
|
||||
if (i < nsignals) {
|
||||
s = stpcpy(s, signalent[i] + 3);
|
||||
}
|
||||
#ifdef SIGRTMIN
|
||||
else if (i >= __SIGRTMIN && i <= __SIGRTMAX) {
|
||||
s += sprintf(s, "RT_%u", i - __SIGRTMIN);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
s += sprintf(s, "%u", i);
|
||||
}
|
||||
sep = ' ';
|
||||
for (i = 0; (i = next_set_bit(mask, i, size * 32)) >= 0; ) {
|
||||
++i;
|
||||
*s++ = sep;
|
||||
if (i < nsignals) {
|
||||
s = stpcpy(s, signalent[i] + 3);
|
||||
}
|
||||
#ifdef SIGRTMIN
|
||||
else if (i >= __SIGRTMIN && i <= __SIGRTMAX) {
|
||||
s += sprintf(s, "RT_%u", i - __SIGRTMIN);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
s += sprintf(s, "%u", i);
|
||||
}
|
||||
sep = ' ';
|
||||
}
|
||||
if (sep == '[')
|
||||
*s++ = sep;
|
||||
@ -277,20 +290,14 @@ sprintsigmask(const char *str, sigset_t *mask)
|
||||
return outstr;
|
||||
}
|
||||
|
||||
static const char *
|
||||
sprintsigmask_long(const char *str, long mask)
|
||||
{
|
||||
sigset_t s;
|
||||
sigemptyset(&s);
|
||||
*(long *)&s = mask;
|
||||
return sprintsigmask(str, &s);
|
||||
}
|
||||
#define tprintsigmask_addr(prefix, mask) \
|
||||
tprints(sprintsigmask_n((prefix), (mask), sizeof(mask)))
|
||||
|
||||
static void
|
||||
printsigmask(sigset_t *mask)
|
||||
{
|
||||
tprints(sprintsigmask("", mask));
|
||||
}
|
||||
#define sprintsigmask_val(prefix, mask) \
|
||||
sprintsigmask_n((prefix), &(mask), sizeof(mask))
|
||||
|
||||
#define tprintsigmask_val(prefix, mask) \
|
||||
tprints(sprintsigmask_n((prefix), &(mask), sizeof(mask)))
|
||||
|
||||
void
|
||||
printsignal(int nr)
|
||||
@ -301,7 +308,7 @@ printsignal(int nr)
|
||||
void
|
||||
print_sigset_addr_len(struct tcb *tcp, long addr, long len)
|
||||
{
|
||||
sigset_t ss;
|
||||
char mask[NSIG / 8];
|
||||
|
||||
if (!addr) {
|
||||
tprints("NULL");
|
||||
@ -315,12 +322,14 @@ print_sigset_addr_len(struct tcb *tcp, long addr, long len)
|
||||
tprintf("%#lx", addr);
|
||||
return;
|
||||
}
|
||||
if (len > NSIG / 8)
|
||||
if (len >= NSIG / 8)
|
||||
len = NSIG / 8;
|
||||
sigemptyset(&ss);
|
||||
if (umoven(tcp, addr, len, (char *)&ss) < 0)
|
||||
else
|
||||
len = (len + 3) & ~3;
|
||||
|
||||
if (umoven(tcp, addr, len, mask) < 0)
|
||||
goto bad;
|
||||
printsigmask(&ss);
|
||||
tprints(sprintsigmask_n("", mask, len));
|
||||
}
|
||||
|
||||
#ifndef ILL_ILLOPC
|
||||
@ -656,10 +665,10 @@ int
|
||||
sys_sigsetmask(struct tcb *tcp)
|
||||
{
|
||||
if (entering(tcp)) {
|
||||
tprints(sprintsigmask_long("", tcp->u_arg[0]));
|
||||
tprintsigmask_val("", tcp->u_arg[0]);
|
||||
}
|
||||
else if (!syserror(tcp)) {
|
||||
tcp->auxstr = sprintsigmask_long("old mask ", tcp->u_rval);
|
||||
tcp->auxstr = sprintsigmask_val("old mask ", tcp->u_rval);
|
||||
return RVAL_HEX | RVAL_STR;
|
||||
}
|
||||
return 0;
|
||||
@ -717,9 +726,9 @@ decode_old_sigaction(struct tcb *tcp, long addr)
|
||||
else
|
||||
tprintf("{%#lx, ", (long) sa.__sa_handler);
|
||||
#ifdef MIPS
|
||||
tprints(sprintsigmask("", (sigset_t *)sa.sa_mask));
|
||||
tprintsigmask_addr("", sa.sa_mask);
|
||||
#else
|
||||
tprints(sprintsigmask_long("", sa.sa_mask));
|
||||
tprintsigmask_val("", sa.sa_mask);
|
||||
#endif
|
||||
tprints(", ");
|
||||
printflags(sigact_flags, sa.sa_flags, "SA_???");
|
||||
@ -823,16 +832,13 @@ sys_sigreturn(struct tcb *tcp)
|
||||
/* more fields follow, which we aren't interested in */
|
||||
};
|
||||
struct arm_ucontext uc;
|
||||
sigset_t sigm;
|
||||
if (umove(tcp, arm_regs.ARM_sp, &uc) < 0)
|
||||
return 0;
|
||||
/* Kernel fills out uc.sc.oldmask too when it sets up signal stack,
|
||||
/*
|
||||
* Kernel fills out uc.sc.oldmask too when it sets up signal stack,
|
||||
* but for sigmask restore, sigreturn syscall uses uc.uc_sigmask instead.
|
||||
* tprints(sprintsigmask_long(") (mask ", uc.sc.oldmask));
|
||||
*/
|
||||
sigemptyset(&sigm);
|
||||
memcpy(&sigm, uc.uc_sigmask, 8);
|
||||
tprints(sprintsigmask(") (mask ", &sigm));
|
||||
tprintsigmask_addr(") (mask ", uc.uc_sigmask);
|
||||
}
|
||||
#elif defined(S390) || defined(S390X)
|
||||
if (entering(tcp)) {
|
||||
@ -842,7 +848,7 @@ sys_sigreturn(struct tcb *tcp)
|
||||
return 0;
|
||||
if (umove(tcp, usp + __SIGNAL_FRAMESIZE, &sc) < 0)
|
||||
return 0;
|
||||
tprints(sprintsigmask(") (mask ", (sigset_t *)&sc.oldmask[0]));
|
||||
tprintsigmask_addr(") (mask ", sc.oldmask);
|
||||
}
|
||||
#elif defined(I386) || defined(X86_64)
|
||||
# if defined(X86_64)
|
||||
@ -902,31 +908,24 @@ sys_sigreturn(struct tcb *tcp)
|
||||
* and after it an additional u32 extramask[1] which holds
|
||||
* upper half of the mask.
|
||||
*/
|
||||
union {
|
||||
sigset_t sig;
|
||||
uint32_t mask[2];
|
||||
} sigmask;
|
||||
uint32_t sigmask[2];
|
||||
if (umove(tcp, *i386_esp_ptr, &signal_stack) < 0)
|
||||
return 0;
|
||||
sigemptyset(&sigmask.sig);
|
||||
sigmask.mask[0] = signal_stack.sc.oldmask;
|
||||
sigmask.mask[1] = signal_stack.extramask[0];
|
||||
tprints(sprintsigmask(") (mask ", &sigmask.sig));
|
||||
sigmask[0] = signal_stack.sc.oldmask;
|
||||
sigmask[1] = signal_stack.extramask[0];
|
||||
tprintsigmask_addr(") (mask ", sigmask);
|
||||
}
|
||||
#elif defined(IA64)
|
||||
if (entering(tcp)) {
|
||||
struct sigcontext sc;
|
||||
long sp;
|
||||
sigset_t sigm;
|
||||
/* offset of sigcontext in the kernel's sigframe structure: */
|
||||
# define SIGFRAME_SC_OFFSET 0x90
|
||||
if (upeek(tcp->pid, PT_R12, &sp) < 0)
|
||||
return 0;
|
||||
if (umove(tcp, sp + 16 + SIGFRAME_SC_OFFSET, &sc) < 0)
|
||||
return 0;
|
||||
sigemptyset(&sigm);
|
||||
memcpy(&sigm, &sc.sc_mask, NSIG / 8);
|
||||
tprints(sprintsigmask(") (mask ", &sigm));
|
||||
tprintsigmask_val(") (mask ", sc.sc_mask);
|
||||
}
|
||||
#elif defined(POWERPC)
|
||||
if (entering(tcp)) {
|
||||
@ -946,7 +945,7 @@ sys_sigreturn(struct tcb *tcp)
|
||||
#endif
|
||||
if (umove(tcp, esp, &sc) < 0)
|
||||
return 0;
|
||||
tprints(sprintsigmask_long(") (mask ", sc.oldmask));
|
||||
tprintsigmask_val(") (mask ", sc.oldmask);
|
||||
}
|
||||
#elif defined(M68K)
|
||||
if (entering(tcp)) {
|
||||
@ -956,7 +955,7 @@ sys_sigreturn(struct tcb *tcp)
|
||||
return 0;
|
||||
if (umove(tcp, usp, &sc) < 0)
|
||||
return 0;
|
||||
tprints(sprintsigmask_long(") (mask ", sc.sc_mask));
|
||||
tprintsigmask_val(") (mask ", sc.sc_mask);
|
||||
}
|
||||
#elif defined(ALPHA)
|
||||
if (entering(tcp)) {
|
||||
@ -966,7 +965,7 @@ sys_sigreturn(struct tcb *tcp)
|
||||
return 0;
|
||||
if (umove(tcp, fp, &sc) < 0)
|
||||
return 0;
|
||||
tprints(sprintsigmask_long(") (mask ", sc.sc_mask));
|
||||
tprintsigmask_val(") (mask ", sc.sc_mask);
|
||||
}
|
||||
#elif defined(SPARC) || defined(SPARC64)
|
||||
if (entering(tcp)) {
|
||||
@ -977,7 +976,7 @@ sys_sigreturn(struct tcb *tcp)
|
||||
perror_msg("sigreturn: umove");
|
||||
return 0;
|
||||
}
|
||||
tprints(sprintsigmask_long(") (mask ", si.si_mask));
|
||||
tprintsigmask_val(") (mask ", si.si_mask);
|
||||
}
|
||||
#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
|
||||
/* This decodes rt_sigreturn. The 64-bit ABIs do not have
|
||||
@ -985,14 +984,13 @@ sys_sigreturn(struct tcb *tcp)
|
||||
if (entering(tcp)) {
|
||||
long sp;
|
||||
struct ucontext uc;
|
||||
sigset_t sigm;
|
||||
if (upeek(tcp->pid, REG_SP, &sp) < 0)
|
||||
return 0;
|
||||
/* There are six words followed by a 128-byte siginfo. */
|
||||
sp = sp + 6 * 4 + 128;
|
||||
if (umove(tcp, sp, &uc) < 0)
|
||||
return 0;
|
||||
tprints(sprintsigmask_long(") (mask ", *(long *) &uc.uc_sigmask));
|
||||
tprintsigmask_val(") (mask ", uc.uc_sigmask);
|
||||
}
|
||||
#elif defined(MIPS)
|
||||
if (entering(tcp)) {
|
||||
@ -1006,7 +1004,7 @@ sys_sigreturn(struct tcb *tcp)
|
||||
sp = regs.regs[29];
|
||||
if (umove(tcp, sp, &si) < 0)
|
||||
return 0;
|
||||
tprints(sprintsigmask_long(") (mask ", si.si_mask));
|
||||
tprintsigmask_val(") (mask ", si.si_mask);
|
||||
}
|
||||
#elif defined(CRISV10) || defined(CRISV32)
|
||||
if (entering(tcp)) {
|
||||
@ -1018,20 +1016,17 @@ sys_sigreturn(struct tcb *tcp)
|
||||
}
|
||||
if (umove(tcp, regs[PT_USP], &sc) < 0)
|
||||
return 0;
|
||||
tprints(sprintsigmask_long(") (mask ", sc.oldmask));
|
||||
tprintsigmask_val(") (mask ", sc.oldmask);
|
||||
}
|
||||
#elif defined(TILE)
|
||||
if (entering(tcp)) {
|
||||
struct ucontext uc;
|
||||
sigset_t sigm;
|
||||
|
||||
/* offset of ucontext in the kernel's sigframe structure */
|
||||
# define SIGFRAME_UC_OFFSET C_ABI_SAVE_AREA_SIZE + sizeof(siginfo_t)
|
||||
if (umove(tcp, tile_regs.sp + SIGFRAME_UC_OFFSET, &uc) < 0)
|
||||
return 0;
|
||||
sigemptyset(&sigm);
|
||||
memcpy(&sigm, &uc.uc_sigmask, NSIG / 8);
|
||||
tprints(sprintsigmask(") (mask ", &sigm));
|
||||
tprintsigmask_val(") (mask ", uc.uc_sigmask);
|
||||
}
|
||||
#elif defined(MICROBLAZE)
|
||||
/* TODO: Verify that this is correct... */
|
||||
@ -1043,7 +1038,7 @@ sys_sigreturn(struct tcb *tcp)
|
||||
return 0;
|
||||
if (umove(tcp, sp, &sc) < 0)
|
||||
return 0;
|
||||
tprints(sprintsigmask_long(") (mask ", sc.oldmask));
|
||||
tprintsigmask_val(") (mask ", sc.oldmask);
|
||||
}
|
||||
#elif defined(XTENSA)
|
||||
/* Xtensa only has rt_sys_sigreturn */
|
||||
@ -1060,7 +1055,7 @@ int
|
||||
sys_siggetmask(struct tcb *tcp)
|
||||
{
|
||||
if (exiting(tcp)) {
|
||||
tcp->auxstr = sprintsigmask_long("mask ", tcp->u_rval);
|
||||
tcp->auxstr = sprintsigmask_val("mask ", tcp->u_rval);
|
||||
}
|
||||
return RVAL_HEX | RVAL_STR;
|
||||
}
|
||||
@ -1069,7 +1064,7 @@ int
|
||||
sys_sigsuspend(struct tcb *tcp)
|
||||
{
|
||||
if (entering(tcp)) {
|
||||
tprints(sprintsigmask_long("", tcp->u_arg[2]));
|
||||
tprintsigmask_val("", tcp->u_arg[2]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1134,10 +1129,10 @@ sys_sigprocmask(struct tcb *tcp)
|
||||
* ret = sigprocmask(how, &new, &old, ...);
|
||||
*/
|
||||
printxval(sigprocmaskcmds, tcp->u_arg[0], "SIG_???");
|
||||
tprints(sprintsigmask_long(", ", tcp->u_arg[1]));
|
||||
tprintsigmask_val(", ", tcp->u_arg[1]);
|
||||
}
|
||||
else if (!syserror(tcp)) {
|
||||
tcp->auxstr = sprintsigmask_long("old mask ", tcp->u_rval);
|
||||
tcp->auxstr = sprintsigmask_val("old mask ", tcp->u_rval);
|
||||
return RVAL_HEX | RVAL_STR;
|
||||
}
|
||||
# else /* !ALPHA */
|
||||
@ -1244,7 +1239,6 @@ static void
|
||||
decode_new_sigaction(struct tcb *tcp, long addr)
|
||||
{
|
||||
struct new_sigaction sa;
|
||||
sigset_t sigset;
|
||||
int r;
|
||||
|
||||
if (!addr) {
|
||||
@ -1306,9 +1300,7 @@ decode_new_sigaction(struct tcb *tcp, long addr)
|
||||
* with wrong sigset size (just returns EINVAL instead).
|
||||
* We just fetch the right size, which is NSIG / 8.
|
||||
*/
|
||||
sigemptyset(&sigset);
|
||||
memcpy(&sigset, &sa.sa_mask, NSIG / 8);
|
||||
printsigmask(&sigset);
|
||||
tprintsigmask_val("", sa.sa_mask);
|
||||
tprints(", ");
|
||||
|
||||
printflags(sigact_flags, sa.sa_flags, "SA_???");
|
||||
|
@ -8,6 +8,11 @@
|
||||
# the 1st is for any architecture with SA_RESTORER, including SPARC;
|
||||
# the 2nd is for any architecture without SA_RESTORER, including ALPHA.
|
||||
|
||||
BEGIN {
|
||||
lines = 5
|
||||
fail = 0
|
||||
}
|
||||
|
||||
# Test 1.
|
||||
NR == 1 && /^rt_sigaction\(SIGUSR2, {SIG_IGN, \[HUP INT\], SA_RESTORER\|SA_RESTART, 0x[0-9a-f]+}, {SIG_DFL, \[\], 0}, (0x[0-9a-f]+, )?(4|8|16)\) = 0$/ {next}
|
||||
NR == 1 && /^rt_sigaction\(SIGUSR2, {SIG_IGN, \[HUP INT\], SA_RESTART}, {SIG_DFL, \[\], 0}, (4|8|16)(, 0x[0-9a-f]+)?\) = 0$/ {next}
|
||||
@ -20,17 +25,26 @@ NR == 2 && /^rt_sigaction\(SIGUSR2, {0x[0-9a-f]+, \[QUIT TERM\], SA_SIGINFO}, {S
|
||||
NR == 3 && /^rt_sigaction\(SIGUSR2, {SIG_DFL, \[\], SA_RESTORER, 0x[0-9a-f]+}, {0x[0-9a-f]+, \[QUIT TERM\], SA_RESTORER\|SA_SIGINFO, 0x[0-9a-f]+}, (0x[0-9a-f]+, )?(4|8|16)\) = 0$/ {next}
|
||||
NR == 3 && /^rt_sigaction\(SIGUSR2, {SIG_DFL, \[\], 0}, {0x[0-9a-f]+, \[QUIT TERM\], SA_SIGINFO}, (4|8|16)(, 0x[0-9a-f]+)?\) = 0$/ {next}
|
||||
|
||||
# Test 4.
|
||||
NR == 4 && /^rt_sigaction\(SIGUSR2, {SIG_DFL, ~\[HUP( ((RT|SIGRT)[^] ]+|[3-9][0-9]|1[0-9][0-9]))*\], SA_RESTORER, 0x[0-9a-f]+}, {SIG_DFL, \[\], SA_RESTORER, 0x[0-9a-f]+}, (0x[0-9a-f]+, )?(4|8|16)\) = 0$/ {next}
|
||||
NR == 4 && /^rt_sigaction\(SIGUSR2, {SIG_DFL, ~\[HUP( ((RT|SIGRT)[^] ]+|[3-9][0-9]|1[0-9][0-9]))*\], 0}, {SIG_DFL, \[\], 0}, (4|8|16)(, 0x[0-9a-f]+)?\) = 0$/ {next}
|
||||
|
||||
# The last line.
|
||||
NR == 4 && /^\+\+\+ exited with 0 \+\+\+$/ {next}
|
||||
NR == lines && /^\+\+\+ exited with 0 \+\+\+$/ {next}
|
||||
|
||||
{
|
||||
print "Line " NR " does not match: " $0
|
||||
exit 1
|
||||
fail=1
|
||||
}
|
||||
|
||||
END {
|
||||
if (NR != 4) {
|
||||
print "Expected 4 lines, found " NR " line(s)."
|
||||
if (NR != lines) {
|
||||
print "Expected " lines " lines, found " NR " line(s)."
|
||||
print ""
|
||||
exit 1
|
||||
}
|
||||
if (fail) {
|
||||
print ""
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
@ -11,26 +11,30 @@ static void handle_signal(int no)
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
struct sigaction sa, sa1, sa2, sa3;
|
||||
struct sigaction sa, sa0;
|
||||
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaddset(&sa.sa_mask, SIGHUP);
|
||||
sigaddset(&sa.sa_mask, SIGINT);
|
||||
sa.sa_flags = SA_RESTART;
|
||||
assert(!sigaction(SIGUSR2, &sa, &sa1));
|
||||
assert(!sigaction(SIGUSR2, &sa, &sa0));
|
||||
|
||||
sa.sa_handler = handle_signal;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaddset(&sa.sa_mask, SIGQUIT);
|
||||
sigaddset(&sa.sa_mask, SIGTERM);
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
assert(!sigaction(SIGUSR2, &sa, &sa2));
|
||||
assert(!sigaction(SIGUSR2, &sa, &sa0));
|
||||
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
assert(!sigaction(SIGUSR2, &sa, &sa3));
|
||||
assert(!sigaction(SIGUSR2, &sa, &sa0));
|
||||
|
||||
sigfillset(&sa.sa_mask);
|
||||
sigdelset(&sa.sa_mask, SIGHUP);
|
||||
assert(!sigaction(SIGUSR2, &sa, &sa0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user