Skip to content

Commit

Permalink
Extract changes from #1320 (#1406)
Browse files Browse the repository at this point in the history
  • Loading branch information
cahirwpz authored Jul 28, 2023
1 parent 8146359 commit 95cc3b2
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 31 deletions.
2 changes: 2 additions & 0 deletions bin/utest/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ LIBWRAP = \
xsetresgid.c \
xsetresuid.c \
xsignal.c \
xsigaction.c \
xsigprocmask.c \
xstat.c \
xsymlink.c \
xunlink.c \
Expand Down
10 changes: 10 additions & 0 deletions bin/utest/libwrap/xsigaction.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include "utest.h"
#include <signal.h>

void xsigaction(int sig, const struct sigaction *restrict act,
struct sigaction *restrict oact) {
int result = sigaction(sig, act, oact);

if (result < 0)
die("sigaction: %s", strerror(errno));
}
10 changes: 10 additions & 0 deletions bin/utest/libwrap/xsigprocmask.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include "utest.h"
#include <signal.h>

void xsigprocmask(int how, const sigset_t *restrict set,
sigset_t *restrict oset) {
int result = sigprocmask(how, set, oset);

if (result < 0)
die("sigprocmask: %s", strerror(errno));
}
55 changes: 28 additions & 27 deletions bin/utest/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>

/* ======= signal_basic ======= */
static volatile int sigusr1_handled = 0;
Expand Down Expand Up @@ -149,7 +150,7 @@ TEST_ADD(signal_cont_masked, 0) {
if (pid == 0) {
/* Block SIGCONT. */
sigset_t mask, old;
__sigemptyset(&mask);
sigemptyset(&mask);
sigaddset(&mask, SIGCONT);
assert(sigprocmask(SIG_BLOCK, &mask, &old) == 0);
/* Even though SIGCONT is blocked, it should wake us up, but it
Expand Down Expand Up @@ -203,7 +204,7 @@ TEST_ADD(signal_mask, 0) {
do {
sched_yield();
sigpending(&set);
} while (!__sigismember(&set, SIGCONT));
} while (!sigismember(&set, SIGCONT));

assert(!sigcont_handled);

Expand All @@ -220,15 +221,15 @@ TEST_ADD(signal_mask, 0) {
/* ======= signal_mask_nonmaskable ======= */
TEST_ADD(signal_mask_nonmaskable, 0) {
sigset_t set, old;
__sigemptyset(&set);
__sigaddset(&set, SIGSTOP);
__sigaddset(&set, SIGKILL);
__sigaddset(&set, SIGUSR1);
sigemptyset(&set);
sigaddset(&set, SIGSTOP);
sigaddset(&set, SIGKILL);
sigaddset(&set, SIGUSR1);
/* The call should succeed, but SIGKILL and SIGSTOP shouldn't be blocked. */
assert(sigprocmask(SIG_BLOCK, &set, &old) == 0);
assert(sigprocmask(SIG_BLOCK, NULL, &set) == 0);
__sigaddset(&old, SIGUSR1);
assert(__sigsetequal(&set, &old));
xsigprocmask(SIG_BLOCK, &set, &old);
xsigprocmask(SIG_BLOCK, NULL, &set);
sigaddset(&old, SIGUSR1);
assert(sigsetequal(&set, &old));
return 0;
}

Expand All @@ -238,11 +239,11 @@ TEST_ADD(signal_sigsuspend, 0) {
xsignal(SIGCONT, sigcont_handler);
xsignal(SIGUSR1, sigusr1_handler);
sigset_t set, old;
__sigemptyset(&set);
__sigaddset(&set, SIGCONT);
__sigaddset(&set, SIGUSR1);
assert(sigprocmask(SIG_BLOCK, &set, &old) == 0);
__sigaddset(&old, SIGCONT);
sigemptyset(&set);
sigaddset(&set, SIGCONT);
sigaddset(&set, SIGUSR1);
xsigprocmask(SIG_BLOCK, &set, &old);
sigaddset(&old, SIGCONT);
pid_t cpid = xfork();
if (cpid == 0) {
for (int i = 0; i < 10; i++) {
Expand All @@ -255,19 +256,19 @@ TEST_ADD(signal_sigsuspend, 0) {
/* Go to sleep with SIGCONT blocked and SIGUSR1 unblocked. */
debug("Calling sigsuspend()...");
sigset_t current;
sigprocmask(SIG_BLOCK, NULL, &current);
assert(__sigismember(&current, SIGUSR1));
assert(!__sigismember(&old, SIGUSR1));
xsigprocmask(SIG_BLOCK, NULL, &current);
assert(sigismember(&current, SIGUSR1));
assert(!sigismember(&old, SIGUSR1));
sigsuspend(&old);
/* Check if mask is set back after waking up */
sigprocmask(SIG_BLOCK, NULL, &set);
assert(__sigsetequal(&set, &current));
xsigprocmask(SIG_BLOCK, NULL, &set);
assert(sigsetequal(&set, &current));
/* SIGUSR1 should have woken us up, but SIGCONT should still be pending. */
assert(sigusr1_handled);
assert(!sigcont_handled);
__sigemptyset(&set);
__sigaddset(&set, SIGCONT);
assert(sigprocmask(SIG_UNBLOCK, &set, NULL) == 0);
sigemptyset(&set);
sigaddset(&set, SIGCONT);
xsigprocmask(SIG_UNBLOCK, &set, NULL);
assert(sigcont_handled);

wait_child_finished(cpid);
Expand All @@ -279,8 +280,8 @@ TEST_ADD(signal_sigsuspend_stop, 0) {
pid_t ppid = getpid();
xsignal(SIGUSR1, sigusr1_handler);
sigset_t set, old;
__sigemptyset(&set);
__sigaddset(&set, SIGUSR1);
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
assert(sigprocmask(SIG_BLOCK, &set, &old) == 0);
pid_t cpid = xfork();
if (cpid == 0) {
Expand Down Expand Up @@ -352,8 +353,8 @@ TEST_ADD(signal_handler_mask, 0) {
pid_t ppid = getpid();
struct sigaction sa = {.sa_handler = yield_handler, .sa_flags = 0};
/* Block SIGUSR1 when executing handler for SIGUSR2. */
__sigemptyset(&sa.sa_mask);
__sigaddset(&sa.sa_mask, SIGUSR1);
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGUSR1);
assert(sigaction(SIGUSR2, &sa, NULL) == 0);
xsignal(SIGUSR1, sigusr1_handler);
xsignal(SIGCONT, sigcont_handler);
Expand Down
6 changes: 6 additions & 0 deletions bin/utest/utest.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,11 @@ void wait_child_continued(pid_t pid);

#include <errno.h>
#include <string.h>
#include <sys/sigtypes.h>

typedef void (*sig_t)(int);
struct stat;
struct sigaction;
struct timezone;
struct timeval;

Expand All @@ -124,6 +126,10 @@ int xopen(const char *path, int flags, ...);
void xpipe(int pipefd[2]);
void xrmdir(const char *pathname);
sig_t xsignal(int sig, sig_t func);
void xsigaction(int sig, const struct sigaction *restrict act,
struct sigaction *restrict oact);
void xsigprocmask(int how, const sigset_t *restrict set,
sigset_t *restrict oset);
void xsetgroups(int size, gid_t *list);
void xsetresuid(uid_t ruid, uid_t euid, uid_t suid);
void xsetresgid(gid_t rgid, gid_t egid, gid_t sgid);
Expand Down
4 changes: 2 additions & 2 deletions bin/utest/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ static void noop_handler(int signo) {
void signal_setup(int signo) {
xsignal(signo, noop_handler);
sigset_t mask;
__sigemptyset(&mask);
sigemptyset(&mask);
sigaddset(&mask, signo);
assert(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
}

void wait_for_signal(int signo) {
sigset_t mask;
__sigfillset(&mask);
sigfillset(&mask);
sigdelset(&mask, signo);
sigsuspend(&mask);
}
Expand Down
4 changes: 4 additions & 0 deletions bin/utest/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
#include <string.h>
#include <sys/mman.h>

static inline int sigsetequal(sigset_t *a, sigset_t *b) {
return memcmp(a, b, sizeof(sigset_t)) == 0;
}

/* Do the necessary setup needed to wait for the signal.
* Must be called before receiving the signal,
* ideally at the very beginning of the test procedure. */
Expand Down
2 changes: 1 addition & 1 deletion include/sys/signal.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ int do_sigaction(signo_t sig, const sigaction_t *act, sigaction_t *oldact);
int do_sigprocmask(int how, const sigset_t *set, sigset_t *oset);
int do_sigsuspend(proc_t *p, const sigset_t *mask);
int do_sigpending(proc_t *p, sigset_t *set);
int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo,
int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *ksi,
struct timespec *timeout);

#endif /* !_KERNEL */
Expand Down
4 changes: 4 additions & 0 deletions include/sys/sigtypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ typedef struct {
uint32_t __bits; /* bit 0 is unused */
} sigset_t;

#if defined(_KERNEL) || defined(_LIBC)

/*
* Macro for manipulating signal masks.
*/
Expand All @@ -33,6 +35,8 @@ typedef struct {
{ (t)->__bits &= (s)->__bits; }
#define __sigfindset(s) (__builtin_ffs((s)->__bits))

#endif /* !_KERNEL */

typedef struct sigaltstack {
void *ss_sp; /* signal stack base */
size_t ss_size; /* signal stack length */
Expand Down
10 changes: 10 additions & 0 deletions lib/libc/gen/sigismember.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <errno.h>
#include <signal.h>

int sigismember(const sigset_t *set, int signo) {
if (signo <= 0 || signo >= NSIG) {
errno = EINVAL;
return -1;
}
return (__sigismember(set, signo));
}
8 changes: 8 additions & 0 deletions sys/kern/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#include <sys/mutex.h>
#include <sys/malloc.h>

#include <sys/siginfo.h>
#include <sys/sigtypes.h>

static KMALLOC_DEFINE(M_SIGNAL, "signal");

/*!\brief Signal properties. */
Expand Down Expand Up @@ -201,6 +204,11 @@ int do_sigsuspend(proc_t *p, const sigset_t *mask) {
return ERESTARTNOHAND;
}

int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *ksi,
timespec_t *tsp) {
return ENOTSUP;
}

int do_sigpending(proc_t *p, sigset_t *set) {
SCOPED_MTX_LOCK(&p->p_lock);
thread_t *td = p->p_thread;
Expand Down
27 changes: 26 additions & 1 deletion sys/kern/syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -1333,7 +1333,32 @@ static int sys_kevent(proc_t *p, kevent_args_t *args, register_t *res) {

static int sys_sigtimedwait(proc_t *p, sigtimedwait_args_t *args,
register_t *res) {
return ENOTSUP;
const sigset_t *u_set = SCARG(args, set);
siginfo_t *u_info = SCARG(args, info);
const timespec_t *u_timeout = SCARG(args, timeout);
sigset_t set;
ksiginfo_t ksi;
timespec_t timeout = {};
int error;

if (u_timeout) {
error = copyin_s(u_timeout, timeout);
if (error)
return error;
}

if ((error = copyin_s(u_set, set)))
return error;

if ((error = do_sigtimedwait(p, set, &ksi, u_timeout ? &timeout : NULL)))
return error;

if (u_info)
error = copyout_s(ksi.ksi_info, u_info);

*res = ksi.ksi_info.si_signo;

return error;
}

static int sys_clock_settime(proc_t *p, clock_settime_args_t *args,
Expand Down

0 comments on commit 95cc3b2

Please sign in to comment.