summaryrefslogtreecommitdiff
path: root/regress
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>2005-05-31 09:27:29 +0000
committerArtur Grabowski <art@cvs.openbsd.org>2005-05-31 09:27:29 +0000
commit44549b9992f504faa3201571571eacb28d451db7 (patch)
treeb10259543d7b9f7a14a88120480be7676653214e /regress
parent5beefe36327bbfeb29ba5841b8afac474e46cf0d (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/Makefile5
-rw-r--r--regress/sys/kern/sigsuspend/sigsuspend.c126
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 */
+}
+
+