diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2005-05-31 09:27:29 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2005-05-31 09:27:29 +0000 |
commit | 44549b9992f504faa3201571571eacb28d451db7 (patch) | |
tree | b10259543d7b9f7a14a88120480be7676653214e /regress | |
parent | 5beefe36327bbfeb29ba5841b8afac474e46cf0d (diff) |
Test the semantics of sigsuspend.
For some reason this test doesn't fail which means the code is correct and
my reading of the code is incorrect. That can be either a good or bad
sign depending on how you look at it.
millert@ says it "looks correct"
Diffstat (limited to 'regress')
-rw-r--r-- | regress/sys/kern/sigsuspend/Makefile | 5 | ||||
-rw-r--r-- | regress/sys/kern/sigsuspend/sigsuspend.c | 126 |
2 files changed, 131 insertions, 0 deletions
diff --git a/regress/sys/kern/sigsuspend/Makefile b/regress/sys/kern/sigsuspend/Makefile new file mode 100644 index 00000000000..cb8bcf90327 --- /dev/null +++ b/regress/sys/kern/sigsuspend/Makefile @@ -0,0 +1,5 @@ +# $OpenBSD: Makefile,v 1.1 2005/05/31 09:27:28 art Exp $ + +PROG= sigsuspend + +.include <bsd.regress.mk> diff --git a/regress/sys/kern/sigsuspend/sigsuspend.c b/regress/sys/kern/sigsuspend/sigsuspend.c new file mode 100644 index 00000000000..2f8e0a92e97 --- /dev/null +++ b/regress/sys/kern/sigsuspend/sigsuspend.c @@ -0,0 +1,126 @@ +/* $OpenBSD: sigsuspend.c,v 1.1 2005/05/31 09:27:28 art Exp $ */ +/* + * Written by Artur Grabowski <art@openbsd.org> 2005, Public domain. + */ +#include <signal.h> +#include <unistd.h> +#include <err.h> +#include <sys/types.h> +#include <sys/wait.h> + +sig_atomic_t gotusr1; +sig_atomic_t gotusr2; + +void +usr1handler(int signo) +{ + gotusr1 = 1; +} + +void +usr2handler(int signo) +{ + gotusr2 = 1; +} + +int +main() +{ + sigset_t set, oset; + struct sigaction sa; + pid_t pid, ppid; + int status; + + ppid = getpid(); + + memset(&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = usr1handler; + if (sigaction(SIGUSR1, &sa, NULL)) + err(1, "sigaction(USR1)"); + + sa.sa_handler = usr2handler; + if (sigaction(SIGUSR2, &sa, NULL)) + err(1, "sigaction(USR2)"); + + /* + * Set the procmask to mask the early USR1 the child will send us. + */ + sigemptyset(&set); + sigaddset(&set, SIGUSR1); + sigaddset(&set, SIGUSR2); + if (sigprocmask(SIG_BLOCK, &set, &oset)) + err(1, "sigprocmask"); + + switch((pid = fork())) { + case 0: + /* + * In the child. + */ + + kill(ppid, SIGUSR1); /* Tell the parent we're ready. */ + + sigemptyset(&set); + sigaddset(&set, SIGUSR2); + sigsuspend(&set); + + /* + * Check that sigsuspend didn't change the signal mask. + */ + if (sigprocmask(SIG_SETMASK, NULL, &oset)) + err(1, "sigprocmask"); + if (!sigismember(&oset, SIGUSR1) || + !sigismember(&oset, SIGUSR2)) + errx(1, "sigprocmask is bad"); + + /* Check that we got the sigusr1 that we expected. */ + if (!gotusr1) + errx(1, "didn't get usr1"); + if (gotusr2) + errx(1, "got incorrect usr2"); + + sigemptyset(&set); + sigaddset(&set, SIGUSR1); + sigsuspend(&set); + + if (!gotusr2) + errx(1, "didn't get usr2"); + + _exit(0); + case -1: + err(1, "fork"); + default: + /* + * In the parent. + * Waiting for the initial USR1 that tells us the child + * is ready. + */ + while (gotusr1 == 0) + sigsuspend(&oset); + + /* + * Check that sigsuspend didn't change the signal mask. + */ + if (sigprocmask(SIG_SETMASK, NULL, &oset)) + err(1, "sigprocmask"); + if (!sigismember(&oset, SIGUSR1) || + !sigismember(&oset, SIGUSR2)) + errx(1, "sigprocmask is bad"); + + /* + * Deliberately send USR2 first to confuse. + */ + kill(pid, SIGUSR2); + kill(pid, SIGUSR1); + + if (waitpid(pid, &status, 0) != pid) + err(1, "waitpid"); + + if (WIFEXITED(status)) + exit(WEXITSTATUS(status)); + exit(1); + } + /* NOTREACHED */ +} + + |