From: Benjamin Berg <benjamin.b...@intel.com>

Add support for sigaction() using the rt_sigaction syscall and implement
the normal sa_mask helpers.

For the uapi definitions, everything is copied into nolibc. This avoids
issues with kernel architecture headers that are not usable with the
rt_sigaction syscall.

Signed-off-by: Benjamin Berg <benjamin.b...@intel.com>

---

v3:
- put everything into signal.h and the new asm-signal.h
- split out sigset_t tests
- actually mark signal_check static
- remove unused string.h include
- fix SIGUSR2 reset
- Use integer for signal_check as the signals are emitted from the
  syscall context.

v2:
- Use newly added macros to check signal emission order
- Add tests for sigset handling
- Restore the default handler after signal test
- make signal_check variable static

v1:
- Update architecture support (adding sh)
- Move sparc sys_rt_sigaction logic into its header
- Add sig_atomic_t
- Use new BITSET_* macros
- Move test into syscall suite
- Various other small changes
---
 tools/include/nolibc/Makefile                |   1 +
 tools/include/nolibc/arch-s390.h             |   4 +-
 tools/include/nolibc/asm-signal.h            | 237 +++++++++++++++++++
 tools/include/nolibc/signal.h                | 179 ++++++++++++++
 tools/include/nolibc/sys.h                   |   2 +-
 tools/include/nolibc/sys/wait.h              |   1 +
 tools/include/nolibc/time.h                  |   2 +-
 tools/include/nolibc/types.h                 |   9 +
 tools/testing/selftests/nolibc/nolibc-test.c | 134 +++++++++++
 9 files changed, 566 insertions(+), 3 deletions(-)
 create mode 100644 tools/include/nolibc/asm-signal.h

diff --git a/tools/include/nolibc/Makefile b/tools/include/nolibc/Makefile
index 143c2d2c2ba6..55db0677cfc3 100644
--- a/tools/include/nolibc/Makefile
+++ b/tools/include/nolibc/Makefile
@@ -25,6 +25,7 @@ endif
 
 arch_file := arch-$(ARCH).h
 all_files := \
+               asm-signal.h \
                compiler.h \
                crt.h \
                ctype.h \
diff --git a/tools/include/nolibc/arch-s390.h b/tools/include/nolibc/arch-s390.h
index df4c3cc713ac..f22f9a6d9887 100644
--- a/tools/include/nolibc/arch-s390.h
+++ b/tools/include/nolibc/arch-s390.h
@@ -5,13 +5,15 @@
 
 #ifndef _NOLIBC_ARCH_S390_H
 #define _NOLIBC_ARCH_S390_H
-#include <linux/signal.h>
 #include <linux/unistd.h>
 
 #include "compiler.h"
 #include "crt.h"
 #include "std.h"
 
+/* For SIGCHLD */
+#include "asm-signal.h"
+
 /* Syscalls for s390:
  *   - registers are 64-bit
  *   - syscall number is passed in r1
diff --git a/tools/include/nolibc/asm-signal.h 
b/tools/include/nolibc/asm-signal.h
new file mode 100644
index 000000000000..7831595745a8
--- /dev/null
+++ b/tools/include/nolibc/asm-signal.h
@@ -0,0 +1,237 @@
+/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
+/*
+ * ASM signal definitions for NOLIBC
+ */
+
+#ifndef _NOLIBC_ASM_SIGNAL_H
+#define _NOLIBC_ASM_SIGNAL_H
+
+/*
+ * This reproduces the kernel headers for the different architectures.
+ */
+
+#include <linux/types.h>
+
+#if defined(__mips__)
+#define _NSIG          128
+#else
+#define _NSIG          64
+#endif
+#define _NSIG_BPW      __BITS_PER_LONG
+#define _NSIG_WORDS    (_NSIG / _NSIG_BPW)
+
+typedef struct {
+       unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+#if defined(__mips__)
+#define SIGHUP          1      /* Hangup (POSIX).  */
+#define SIGINT          2      /* Interrupt (ANSI).  */
+#define SIGQUIT                 3      /* Quit (POSIX).  */
+#define SIGILL          4      /* Illegal instruction (ANSI).  */
+#define SIGTRAP                 5      /* Trace trap (POSIX).  */
+#define SIGIOT          6      /* IOT trap (4.2 BSD).  */
+#define SIGABRT                 SIGIOT /* Abort (ANSI).  */
+#define SIGEMT          7
+#define SIGFPE          8      /* Floating-point exception (ANSI).  */
+#define SIGKILL                 9      /* Kill, unblockable (POSIX).  */
+#define SIGBUS         10      /* BUS error (4.2 BSD).  */
+#define SIGSEGV                11      /* Segmentation violation (ANSI).  */
+#define SIGSYS         12
+#define SIGPIPE                13      /* Broken pipe (POSIX).  */
+#define SIGALRM                14      /* Alarm clock (POSIX).  */
+#define SIGTERM                15      /* Termination (ANSI).  */
+#define SIGUSR1                16      /* User-defined signal 1 (POSIX).  */
+#define SIGUSR2                17      /* User-defined signal 2 (POSIX).  */
+#define SIGCHLD                18      /* Child status has changed (POSIX).  */
+#define SIGCLD         SIGCHLD /* Same as SIGCHLD (System V).  */
+#define SIGPWR         19      /* Power failure restart (System V).  */
+#define SIGWINCH       20      /* Window size change (4.3 BSD, Sun).  */
+#define SIGURG         21      /* Urgent condition on socket (4.2 BSD).  */
+#define SIGIO          22      /* I/O now possible (4.2 BSD).  */
+#define SIGPOLL                SIGIO   /* Pollable event occurred (System V).  
*/
+#define SIGSTOP                23      /* Stop, unblockable (POSIX).  */
+#define SIGTSTP                24      /* Keyboard stop (POSIX).  */
+#define SIGCONT                25      /* Continue (POSIX).  */
+#define SIGTTIN                26      /* Background read from tty (POSIX).  */
+#define SIGTTOU                27      /* Background write to tty (POSIX).  */
+#define SIGVTALRM      28      /* Virtual alarm clock (4.2 BSD).  */
+#define SIGPROF                29      /* Profiling alarm clock (4.2 BSD).  */
+#define SIGXCPU                30      /* CPU limit exceeded (4.2 BSD).  */
+#define SIGXFSZ                31      /* File size limit exceeded (4.2 BSD).  
*/
+
+#elif defined(__sparc__)
+/* On the Sparc the signal handlers get passed a 'sub-signal' code
+ * for certain signal types, which we document here.
+ */
+#define SIGHUP          1
+#define SIGINT          2
+#define SIGQUIT                 3
+#define SIGILL          4
+#define    SUBSIG_STACK       0
+#define    SUBSIG_ILLINST     2
+#define    SUBSIG_PRIVINST    3
+#define    SUBSIG_BADTRAP(t)  (0x80 + (t))
+
+#define SIGTRAP                 5
+#define SIGABRT                 6
+#define SIGIOT          6
+
+#define SIGEMT           7
+#define    SUBSIG_TAG    10
+
+#define SIGFPE          8
+#define    SUBSIG_FPDISABLED     0x400
+#define    SUBSIG_FPERROR        0x404
+#define    SUBSIG_FPINTOVFL      0x001
+#define    SUBSIG_FPSTSIG        0x002
+#define    SUBSIG_IDIVZERO       0x014
+#define    SUBSIG_FPINEXACT      0x0c4
+#define    SUBSIG_FPDIVZERO      0x0c8
+#define    SUBSIG_FPUNFLOW       0x0cc
+#define    SUBSIG_FPOPERROR      0x0d0
+#define    SUBSIG_FPOVFLOW       0x0d4
+
+#define SIGKILL                 9
+#define SIGBUS          10
+#define    SUBSIG_BUSTIMEOUT    1
+#define    SUBSIG_ALIGNMENT     2
+#define    SUBSIG_MISCERROR     5
+
+#define SIGSEGV                11
+#define    SUBSIG_NOMAPPING     3
+#define    SUBSIG_PROTECTION    4
+#define    SUBSIG_SEGERROR      5
+
+#define SIGSYS         12
+
+#define SIGPIPE                13
+#define SIGALRM                14
+#define SIGTERM                15
+#define SIGURG          16
+
+/* SunOS values which deviate from the Linux/i386 ones */
+#define SIGSTOP                17
+#define SIGTSTP                18
+#define SIGCONT                19
+#define SIGCHLD                20
+#define SIGTTIN                21
+#define SIGTTOU                22
+#define SIGIO          23
+#define SIGPOLL                SIGIO   /* SysV name for SIGIO */
+#define SIGXCPU                24
+#define SIGXFSZ                25
+#define SIGVTALRM      26
+#define SIGPROF                27
+#define SIGWINCH       28
+#define SIGLOST                29
+#define SIGPWR         SIGLOST
+#define SIGUSR1                30
+#define SIGUSR2                31
+
+#else /* asm-generic signal definitions */
+#define SIGHUP          1
+#define SIGINT          2
+#define SIGQUIT                 3
+#define SIGILL          4
+#define SIGTRAP                 5
+#define SIGABRT                 6
+#define SIGIOT          6
+#define SIGBUS          7
+#define SIGFPE          8
+#define SIGKILL                 9
+#define SIGUSR1                10
+#define SIGSEGV                11
+#define SIGUSR2                12
+#define SIGPIPE                13
+#define SIGALRM                14
+#define SIGTERM                15
+#define SIGSTKFLT      16
+#define SIGCHLD                17
+#define SIGCONT                18
+#define SIGSTOP                19
+#define SIGTSTP                20
+#define SIGTTIN                21
+#define SIGTTOU                22
+#define SIGURG         23
+#define SIGXCPU                24
+#define SIGXFSZ                25
+#define SIGVTALRM      26
+#define SIGPROF                27
+#define SIGWINCH       28
+#define SIGIO          29
+#define SIGPOLL                SIGIO
+/*
+#define SIGLOST                29
+*/
+#define SIGPWR         30
+#define SIGSYS         31
+#define        SIGUNUSED       31
+#endif
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN       32
+#ifndef SIGRTMAX
+#define SIGRTMAX       _NSIG
+#endif
+
+#if !defined MINSIGSTKSZ || !defined SIGSTKSZ
+#if defined(__aarch64__)
+#define MINSIGSTKSZ     5120
+#define SIGSTKSZ       16384
+#elif defined(__loongarch__) || defined(__sparc__)
+#define MINSIGSTKSZ     4096
+#define SIGSTKSZ       16384
+#elif defined(__powerpc64__)
+#define MINSIGSTKSZ     8192
+#define SIGSTKSZ       32768
+#else
+#define MINSIGSTKSZ     2048
+#define SIGSTKSZ        8192
+#endif
+#endif
+
+#if defined(__mips__)
+#define SA_ONSTACK      0x08000000
+#define SA_RESETHAND    0x80000000
+#define SA_RESTART      0x10000000
+#define SA_SIGINFO      0x00000008
+#define SA_NODEFER      0x40000000
+#define SA_NOCLDWAIT    0x00010000
+#define SA_NOCLDSTOP    0x00000001
+
+#elif defined(__sparc__)
+#define _SV_SSTACK    1u
+#define _SV_INTR      2u
+#define _SV_RESET     4u
+#define _SV_IGNCHILD  8u
+
+#define SA_NOCLDSTOP    _SV_IGNCHILD
+#define SA_STACK        _SV_SSTACK
+#define SA_ONSTACK      _SV_SSTACK
+#define SA_RESTART      _SV_INTR
+#define SA_RESETHAND    _SV_RESET
+#define SA_NODEFER      0x20u
+#define SA_NOCLDWAIT    0x100u
+#define SA_SIGINFO      0x200u
+
+#else
+#define SA_NOCLDSTOP    0x00000001
+#define SA_NOCLDWAIT    0x00000002
+#define SA_SIGINFO      0x00000004
+#define SA_UNSUPPORTED  0x00000400
+#define SA_EXPOSE_TAGBITS       0x00000800
+#define SA_ONSTACK      0x08000000
+#define SA_RESTART      0x10000000
+#define SA_NODEFER      0x40000000
+#define SA_RESETHAND    0x80000000
+#endif
+
+#define SA_NOMASK       SA_NODEFER
+#define SA_ONESHOT      SA_RESETHAND
+
+#if defined(__ARM_EABI__) || defined(__aarch64__) || defined(__m68k__) || 
defined(__powerpc__) || defined(__s390x__) || defined(__s390__) || 
defined(__sh__) || defined(__i386__) || defined(__x86_64__)
+#define SA_RESTORER    0x04000000
+#endif
+
+#endif /* _NOLIBC_ASM_SIGNAL_H */
\ No newline at end of file
diff --git a/tools/include/nolibc/signal.h b/tools/include/nolibc/signal.h
index ac13e53ac31d..8a71bba8c1b6 100644
--- a/tools/include/nolibc/signal.h
+++ b/tools/include/nolibc/signal.h
@@ -14,6 +14,46 @@
 #include "arch.h"
 #include "types.h"
 #include "sys.h"
+#include <asm/siginfo.h>
+#include "asm-signal.h"
+
+typedef void __signalfn_t(int);
+typedef __signalfn_t *__sighandler_t;
+
+typedef void __restorefn_t(void);
+typedef __restorefn_t *__sigrestore_t;
+
+#define SIG_DFL ((__sighandler_t)0)     /* default signal handling */
+#define SIG_IGN ((__sighandler_t)1)     /* ignore signal */
+#define SIG_ERR ((__sighandler_t)-1)    /* error return from signal */
+
+#if defined(__mips__)
+struct sigaction {
+        unsigned int    sa_flags;
+        __sighandler_t  sa_handler;
+        sigset_t        sa_mask;
+};
+#else
+struct sigaction {
+       __sighandler_t sa_handler;
+       unsigned long sa_flags;
+#if defined(SA_RESTORER) || defined(__sparc__)
+       __sigrestore_t sa_restorer;
+#endif
+       sigset_t sa_mask;               /* mask last for extensibility */
+};
+#endif
+
+typedef struct sigaltstack {
+       void *ss_sp;
+       int ss_flags;
+       __kernel_size_t ss_size;
+} stack_t;
+
+#ifndef __sig_atomic_t_defined
+#define __sig_atomic_t_defined 1
+typedef int sig_atomic_t;
+#endif
 
 /* This one is not marked static as it's needed by libgcc for divide by zero */
 int raise(int signal);
@@ -23,4 +63,143 @@ int raise(int signal)
        return sys_kill(sys_getpid(), signal);
 }
 
+/*
+ * sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
+ */
+#if defined(__sparc__)
+/*
+ * Sparc needs a restorer, which needs to be implemented in assembler and
+ * passed as a separate argument.
+ */
+
+void __nolibc_sa_restorer(void);
+void __nolibc_sa_restorer_wrapper(void);
+void __attribute__((weak,noreturn)) __nolibc_entrypoint __no_stack_protector
+__nolibc_sa_restorer_wrapper(void)
+{
+       /* The C function will have a prologue corrupting "sp" */
+       __asm__  volatile (
+               ".section .text\n"
+               ".align 4\n"
+               ".type __nolibc_sa_restorer, @function\n"
+               "__nolibc_sa_restorer:\n"
+               "nop\n"
+               "nop\n"
+               "mov %0, %%g1 \n"
+#ifdef __arch64__
+               "t 0x6d\n"
+#else
+               "t 0x10\n"
+#endif
+               ".size __nolibc_sa_restorer, .-__nolibc_sa_restorer\n"
+               :: "n"(__NR_rt_sigreturn)
+       );
+       __nolibc_entrypoint_epilogue();
+}
+
+static __attribute__((unused))
+int sys_rt_sigaction(int signum, const struct sigaction *act, struct sigaction 
*oldact)
+{
+       struct sigaction real_act = *act;
+
+       /* Otherwise we would need to use sigreturn instead of rt_sigreturn */
+       real_act.sa_flags |= SA_SIGINFO;
+
+       return my_syscall5(__NR_rt_sigaction, signum, &real_act, oldact,
+                          __nolibc_sa_restorer, sizeof(act->sa_mask));
+}
+
+#else
+#if defined(__x86_64__) || defined(__i386_) || defined(__powerpc__)
+static __no_stack_protector
+void __nolibc_sa_restorer(void)
+{
+       my_syscall0(__NR_rt_sigreturn);
+}
+#endif
+
+static __attribute__((unused))
+int sys_rt_sigaction(int signum, const struct sigaction *act, struct sigaction 
*oldact)
+{
+       struct sigaction real_act = *act;
+#if defined(__x86_64__) || defined(__i386_) || defined(__powerpc__)
+       if (!(real_act.sa_flags & SA_RESTORER)) {
+               real_act.sa_flags |= SA_RESTORER;
+               real_act.sa_restorer = __nolibc_sa_restorer;
+       }
+#endif
+#if defined(__i386__)
+       /* Otherwise we would need to use sigreturn instead of rt_sigreturn */
+       real_act.sa_flags |= SA_SIGINFO;
+#endif
+
+       return my_syscall4(__NR_rt_sigaction, signum, &real_act, oldact,
+                          sizeof(act->sa_mask));
+}
+#endif
+
+static __attribute__((unused))
+int sigaction(int signum, const struct sigaction *act, struct sigaction 
*oldact)
+{
+       return __sysret(sys_rt_sigaction(signum, act, oldact));
+}
+
+/*
+ * int sigemptyset(sigset_t *set)
+ */
+static __attribute__((unused))
+int sigemptyset(sigset_t *set)
+{
+       __NOLIBC_BITMASK_ZERO(set->sig);
+       return 0;
+}
+
+/*
+ * int sigfillset(sigset_t *set)
+ */
+static __attribute__((unused))
+int sigfillset(sigset_t *set)
+{
+       __NOLIBC_BITMASK_FILL(set->sig);
+       return 0;
+}
+
+/*
+ * int sigaddset(sigset_t *set, int signum)
+ */
+static __attribute__((unused))
+int sigaddset(sigset_t *set, int signum)
+{
+       if (signum < 1 || signum > _NSIG)
+               return __sysret(-EINVAL);
+
+       __NOLIBC_BITMASK_SET(signum - 1, set->sig);
+       return 0;
+}
+
+/*
+ * int sigdelset(sigset_t *set, int signum)
+ */
+static __attribute__((unused))
+int sigdelset(sigset_t *set, int signum)
+{
+       if (signum < 1 || signum > _NSIG)
+               return __sysret(-EINVAL);
+
+       __NOLIBC_BITMASK_CLEAR(signum - 1, set->sig);
+       return 0;
+}
+
+/*
+ * int sigismember(sigset_t *set, int signum)
+ */
+static __attribute__((unused))
+int sigismember(sigset_t *set, int signum)
+{
+       if (signum < 1 || signum > _NSIG)
+               return __sysret(-EINVAL);
+
+       return __NOLIBC_BITMASK_TEST(signum - 1, set->sig);
+}
+
 #endif /* _NOLIBC_SIGNAL_H */
diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h
index 295e71d34aba..a790e816565b 100644
--- a/tools/include/nolibc/sys.h
+++ b/tools/include/nolibc/sys.h
@@ -14,7 +14,6 @@
 
 /* system includes */
 #include <linux/unistd.h>
-#include <linux/signal.h>  /* for SIGCHLD */
 #include <linux/termios.h>
 #include <linux/mman.h>
 #include <linux/fs.h>
@@ -28,6 +27,7 @@
 #include "errno.h"
 #include "stdarg.h"
 #include "types.h"
+#include "asm-signal.h" /* for SIGCHLD */
 
 
 /* Syscall return helper: takes the syscall value in argument and checks for an
diff --git a/tools/include/nolibc/sys/wait.h b/tools/include/nolibc/sys/wait.h
index 56ddb806da7f..e2aa90cc3cf3 100644
--- a/tools/include/nolibc/sys/wait.h
+++ b/tools/include/nolibc/sys/wait.h
@@ -10,6 +10,7 @@
 #ifndef _NOLIBC_SYS_WAIT_H
 #define _NOLIBC_SYS_WAIT_H
 
+#include <asm/siginfo.h>
 #include "../arch.h"
 #include "../std.h"
 #include "../types.h"
diff --git a/tools/include/nolibc/time.h b/tools/include/nolibc/time.h
index d02bc44d2643..6734a3a702a6 100644
--- a/tools/include/nolibc/time.h
+++ b/tools/include/nolibc/time.h
@@ -15,7 +15,7 @@
 #include "types.h"
 #include "sys.h"
 
-#include <linux/signal.h>
+#include <asm/siginfo.h>
 #include <linux/time.h>
 
 static __inline__
diff --git a/tools/include/nolibc/types.h b/tools/include/nolibc/types.h
index f7f2ddf41e89..7e205386b72c 100644
--- a/tools/include/nolibc/types.h
+++ b/tools/include/nolibc/types.h
@@ -152,6 +152,15 @@
                        (*__set)[__idx] = 0;                            \
        } while (0)
 
+#define __NOLIBC_BITMASK_FILL(set) do {                                        
\
+               __typeof__(set) *__set = &(set);                        \
+               int __idx;                                              \
+               int __size = sizeof(*__set) / sizeof(**__set);          \
+               __typeof__(**__set) __zero = 0;                         \
+               for (__idx = 0; __idx < __size; __idx++)                \
+                       (*__set)[__idx] = ~__zero;                      \
+       } while (0)
+
 #define FD_SETIDXMASK (8 * sizeof(unsigned long))
 #define FD_SETBITMASK (8 * sizeof(unsigned long)-1)
 
diff --git a/tools/testing/selftests/nolibc/nolibc-test.c 
b/tools/testing/selftests/nolibc/nolibc-test.c
index 180f0436127a..75b96eaa4c65 100644
--- a/tools/testing/selftests/nolibc/nolibc-test.c
+++ b/tools/testing/selftests/nolibc/nolibc-test.c
@@ -1269,6 +1269,138 @@ int test_namespace(void)
        return ret;
 }
 
+int test_sigset_t(int test_idx)
+{
+       int llen;
+       int ret = 0;
+
+#ifdef NOLIBC
+       if (is_nolibc) {
+               sigset_t sigset;
+
+               sigfillset(&sigset);
+               llen = printf("    sigset.sig[0] (full): ");
+               EXPECT_EQ(1, sigset.sig[0],
+                       ~(__typeof__(sigset.sig[0]))0);
+               llen = printf("    sigset.sig[%d] (full): ", (int)_NSIG_WORDS - 
1);
+               EXPECT_EQ(1, sigset.sig[_NSIG_WORDS - 1],
+                       ~(__typeof__(sigset.sig[0]))0);
+
+               sigemptyset(&sigset);
+               llen = printf("    sigset.sig[0] (empty): ");
+               EXPECT_EQ(1, sigset.sig[0], 0);
+               llen = printf("    sigset.sig[%d] (empty): ", (int)_NSIG_WORDS 
- 1);
+               EXPECT_EQ(1, sigset.sig[_NSIG_WORDS - 1], 0);
+
+               /* SIGUSR2 is always in the first word */
+               sigaddset(&sigset, SIGUSR2);
+               llen = printf("    sigset.sig[0] (SIGUSR2 set): ");
+               EXPECT_EQ(1, sigset.sig[0], 1 << (SIGUSR2 - 1));
+
+               llen = printf("    sigset.sig[0] (test SIGUSR2): ");
+               EXPECT_NZ(1, sigismember(&sigset, SIGUSR2));
+
+               sigdelset(&sigset, SIGUSR2);
+               llen = printf("    sigset.sig[0] (SIGUSR2 unset): ");
+               EXPECT_ZR(1, sigismember(&sigset, SIGUSR2));
+
+               /* _NSIG is the highest valid number and may not be in the 
first word */
+               sigaddset(&sigset, _NSIG);
+               llen = printf("    sigset.sig[%d] (_NSIG set): ", 
(int)_NSIG_WORDS - 1);
+               EXPECT_EQ(1, sigset.sig[_NSIG_WORDS - 1],
+                       1UL << (_NSIG - (_NSIG_WORDS - 1) * _NSIG_BPW - 1));
+
+               llen = printf("    sigset.sig[%d] (test _NSIG): ", 
(int)_NSIG_WORDS - 1);
+               EXPECT_NZ(1, sigismember(&sigset, _NSIG));
+
+               sigdelset(&sigset, _NSIG);
+               llen = printf("    sigset.sig[%d] (_NSIG unset): ", 
(int)_NSIG_WORDS - 1);
+               EXPECT_ZR(1, sigismember(&sigset, _NSIG));
+
+               llen = printf("%d %s", test_idx, "sigset_t");
+               EXPECT_EQ(1, ret, 0);
+       } else
+#endif
+       {
+               llen = printf("%d %s", test_idx, "sigset_t");
+               result(llen, SKIPPED);
+       }
+
+       return ret;
+}
+
+static int signal_check;
+
+static void sighandler(int signum)
+{
+       if (signum == SIGUSR1) {
+               kill(getpid(), SIGUSR2);
+               /* The second step has not run because SIGUSR2 is masked */
+               signal_check = 0x1;
+       } else {
+               signal_check |= 0x2;
+       }
+}
+
+int test_signals(int test_idx)
+{
+       struct sigaction sa = {
+               .sa_flags = 0,
+               .sa_handler = sighandler,
+       };
+       struct sigaction sa_old = {
+               /* Anything other than SIG_DFL */
+               .sa_handler = sighandler,
+       };
+       int llen; /* line length */
+       int ret = 0;
+       int res;
+
+       signal_check = 0;
+
+       /* sa_mask is empty at this point, set SIGUSR2 to verify masking */
+       sigaddset(&sa.sa_mask, SIGUSR2);
+
+       res = sigaction(SIGUSR1, &sa, &sa_old);
+       llen = printf("    register SIGUSR1:");
+       EXPECT_SYSZR(1, res);
+       if (res)
+               goto out;
+
+       llen = printf("    sa_old.sa_handler: SIG_DFL (%p)", SIG_DFL);
+       EXPECT_PTREQ(1, SIG_DFL, sa_old.sa_handler);
+       if (res)
+               goto out;
+
+       res = sigaction(SIGUSR2, &sa, NULL);
+       llen = printf("    register SIGUSR2");
+       EXPECT_SYSZR(1, res);
+       if (res)
+               goto out;
+
+       /* Trigger the first signal. */
+       kill(getpid(), SIGUSR1);
+
+       /* Check the two signal handlers ran in the expected order */
+       llen = printf("    signal emission: ");
+       EXPECT_EQ(1, signal_check, 0x3);
+
+out:
+       sa.sa_handler = SIG_DFL;
+       res = sigaction(SIGUSR1, &sa, NULL);
+       llen = printf("    restore SIGUSR1");
+       EXPECT_SYSZR(1, res);
+
+       res = sigaction(SIGUSR2, &sa, NULL);
+       llen = printf("    restore SIGUSR2");
+       EXPECT_SYSZR(1, res);
+
+       llen = printf("%d %s", test_idx, "sigaction");
+       EXPECT_EQ(1, ret, 0);
+
+       return ret;
+}
+
 /* Run syscall tests between IDs <min> and <max>.
  * Return 0 on success, non-zero on failure.
  */
@@ -1397,6 +1529,8 @@ int run_syscall(int min, int max)
                CASE_TEST(syscall_noargs);    EXPECT_SYSEQ(1, 
syscall(__NR_getpid), getpid()); break;
                CASE_TEST(syscall_args);      EXPECT_SYSER(1, 
syscall(__NR_statx, 0, NULL, 0, 0, NULL), -1, EFAULT); break;
                CASE_TEST(namespace);         EXPECT_SYSZR(euid0 && proc, 
test_namespace()); break;
+               case __LINE__:                ret += test_sigset_t(test); break;
+               case __LINE__:                ret += test_signals(test); break;
                case __LINE__:
                        return ret; /* must be last */
                /* note: do not set any defaults so as to permit holes above */
-- 
2.50.1


Reply via email to