diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2004-08-05 02:58:36 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2004-08-05 02:58:36 +0000 |
commit | a64cb921168a5ce2de1ef73836282ce242afcc91 (patch) | |
tree | b72e4468b8e1f2ff48aa4b4efeb3fed684288784 /regress/sys | |
parent | a00a0a9743aad3e59bf63f6c2cfee34fa48c4fbf (diff) |
A test that tests sends such a huge amount of signals that something
should happen if signal delivery is not robust.
Diffstat (limited to 'regress/sys')
-rw-r--r-- | regress/sys/kern/signal-stress/Makefile | 5 | ||||
-rw-r--r-- | regress/sys/kern/signal-stress/signal-stress.c | 176 |
2 files changed, 181 insertions, 0 deletions
diff --git a/regress/sys/kern/signal-stress/Makefile b/regress/sys/kern/signal-stress/Makefile new file mode 100644 index 00000000000..84b8773055f --- /dev/null +++ b/regress/sys/kern/signal-stress/Makefile @@ -0,0 +1,5 @@ +# $OpenBSD: Makefile,v 1.1 2004/08/05 02:58:35 art Exp $ + +PROG= signal-stress + +.include <bsd.regress.mk> diff --git a/regress/sys/kern/signal-stress/signal-stress.c b/regress/sys/kern/signal-stress/signal-stress.c new file mode 100644 index 00000000000..ab769016dcb --- /dev/null +++ b/regress/sys/kern/signal-stress/signal-stress.c @@ -0,0 +1,176 @@ +/* $OpenBSD: signal-stress.c,v 1.1 2004/08/05 02:58:35 art Exp $ */ +/* + * Written by Artur Grabowski <art@openbsd.org> 2004 Public Domain. + */ +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/wait.h> + +#include <signal.h> +#include <unistd.h> +#include <stdlib.h> +#include <err.h> + +int nprocs, nsigs; +pid_t *pids; +pid_t next, prev; +sig_atomic_t usr1, usr2; + +void +sighand(int sig) +{ + if (sig == SIGUSR1 && ++usr1 <= nsigs) { + if (kill(next, sig)) + _exit(1); + } + if (sig == SIGUSR2 && ++usr2 <= nsigs) { + if (kill(prev, sig)) + _exit(1); + } +} + +void +do_child(void) +{ + int i; + + /* + * Step 1 - suspend and wait for SIGCONT so that all siblings have + * been started before the next step. + */ + raise(SIGSTOP); + + /* Find our neighbours. */ + for (i = 0; i < nprocs; i++) { + if (pids[i] != getpid()) + continue; + if (i + 1 == nprocs) + next = pids[0]; + else + next = pids[i + 1]; + if (i == 0) + prev = pids[nprocs - 1]; + else + prev = pids[i - 1]; + } + + signal(SIGUSR1, sighand); + signal(SIGUSR2, sighand); + + /* Step 2 - wait again until everyone is ready. */ + raise(SIGSTOP); + + while (usr1 < nsigs || usr2 < nsigs) + pause(); + + /* Step 3 - wait again until everyone is ready. */ + raise(SIGSTOP); +} + +void +wait_stopped(pid_t pid) +{ + int status; + + if (waitpid(pid, &status, WUNTRACED) != pid) + err(1, "waitpid"); + if (!WIFSTOPPED(status)) + errx(1, "child %d not stopped", pid); +} + +void +cleanup(void) +{ + int i; + + for (i = 0; i < nprocs; i++) + kill(pids[i], 9); +} + +void +alrmhand(int sig) +{ + cleanup(); + _exit(1); +} + +int +main() +{ + int i; + pid_t pid; + + nprocs = 100; + + nsigs = 1000; + + if ((pids = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE, + MAP_ANON|MAP_SHARED, -1, 0)) == MAP_FAILED) + err(1, "mmap"); + + for (i = 0; i < nprocs; i++) { + switch((pid = fork())) { + case 0: + do_child(); + _exit(0); + case -1: + err(1, "fork"); + } + pids[i] = pid; + } + + atexit(cleanup); + signal(SIGALRM, alrmhand); + alarm(120); /* Die after two minutes. */ + + /* Step 1. Wait until all children have went to sleep */ + for (i = 0; i < nprocs; i++) + wait_stopped(pids[i]); + /* And wake them */ + for (i = 0; i < nprocs; i++) + kill(pids[i], SIGCONT); + + /* Step 2. Repeat. */ + for (i = 0; i < nprocs; i++) + wait_stopped(pids[i]); + for (i = 0; i < nprocs; i++) + kill(pids[i], SIGCONT); + + /* + * Now all children are ready for action. + * Send the first signals and wait until they all exit. + */ + kill(pids[arc4random() % nprocs], SIGUSR1); + kill(pids[arc4random() % nprocs], SIGUSR2); + + /* + * The signal game is running, now insert noise in the process. + */ + for (i = 0; i < nprocs; i++) { + pid_t pid = pids[arc4random() % nprocs]; + kill(pid, SIGSTOP); + wait_stopped(pid); + kill(pid, SIGCONT); + } + + + /* Step 3. Repeat. */ + for (i = 0; i < nprocs; i++) + wait_stopped(pids[i]); + for (i = 0; i < nprocs; i++) + kill(pids[i], SIGCONT); + + /* Wait for everyone to finish. */ + for (i = 0; i < nprocs; i++) { + int status; + + if (waitpid(pids[i], &status, WUNTRACED) != pids[i]) + err(1, "waitpid"); + if (!WIFEXITED(status)) + errx(1, "child %d not stopped (%d)", pids[i], status); + if (WEXITSTATUS(status) != 0) + warnx("child %d status: %d", i, status); + } + + return (0); +} |