summaryrefslogtreecommitdiff
path: root/regress/sys/kern/kqueue/kqueue-process.c
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>2002-03-02 21:48:06 +0000
committerArtur Grabowski <art@cvs.openbsd.org>2002-03-02 21:48:06 +0000
commit16a72cc1001be69b5793f563e912d3dbceed871d (patch)
treeed19b3cdabaa0b7409757ae53345e8eb950cf76f /regress/sys/kern/kqueue/kqueue-process.c
parent4c655c8762a5d63e4253d66a151de24a93c96120 (diff)
A start for testing EVFILT_PROC, not done yet, but this is a good check point.
Diffstat (limited to 'regress/sys/kern/kqueue/kqueue-process.c')
-rw-r--r--regress/sys/kern/kqueue/kqueue-process.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/regress/sys/kern/kqueue/kqueue-process.c b/regress/sys/kern/kqueue/kqueue-process.c
new file mode 100644
index 00000000000..b9112ca1a60
--- /dev/null
+++ b/regress/sys/kern/kqueue/kqueue-process.c
@@ -0,0 +1,133 @@
+/* $OpenBSD: kqueue-process.c,v 1.1 2002/03/02 21:48:05 art Exp $ */
+/*
+ * Written by Artur Grabowski <art@openbsd.org> 2002 Public Domain
+ */
+
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/wait.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <unistd.h>
+#include <signal.h>
+
+static int process_child(void);
+
+#define ASS(cond, mess) do { if (!(cond)) { mess; return 1; } } while (0)
+
+#define ASSX(cond) ASS(cond, warnx("assertion " #cond " failed on line %d", __LINE__))
+
+void
+usr1handler(int signum)
+{
+ /* nada */
+}
+
+int
+do_process(void)
+{
+ struct kevent ke;
+ int kq, status;
+ pid_t pid, pid2;
+ int didfork, didchild;
+ int i;
+ struct timespec ts;
+
+ /*
+ * Timeout in case something doesn't work.
+ */
+ ts.tv_sec = 10;
+ ts.tv_nsec = 0;
+
+ ASS((kq = kqueue()) >= 0, warn("kqueue"));
+
+ /*
+ * Install a signal handler so that we can use pause() to synchronize
+ * with the child with the parent.
+ */
+ signal(SIGUSR1, usr1handler);
+
+ switch ((pid = fork())) {
+ case -1:
+ err(1, "fork");
+ case 0:
+ _exit(process_child());
+ }
+
+ sleep(2); /* wait for child to settle down. */
+
+ EV_SET(&ke, pid, EVFILT_PROC, EV_ADD|EV_ENABLE|EV_CLEAR,
+ NOTE_EXIT|NOTE_FORK|NOTE_EXEC|NOTE_TRACK, 0, NULL);
+ ASS(kevent(kq, &ke, 1, NULL, 0, NULL) == 0,
+ warn("can't register events on kqueue"));
+
+ kill(pid, SIGUSR1); /* sync 1 */
+
+ didfork = didchild = 0;
+
+ for (i = 0; i < 2; i++) {
+ ASS(kevent(kq, NULL, 0, &ke, 1, &ts) == 1,
+ warnx("didn't receive event"));
+ ASSX(ke.filter == EVFILT_PROC);
+ switch (ke.fflags) {
+ case NOTE_CHILD:
+ didchild = 1;
+ ASSX((pid_t)ke.data == pid);
+ pid2 = ke.ident;
+ fprintf(stderr, "child %d\n", pid2);
+ break;
+ case NOTE_FORK:
+ didfork = 1;
+ ASSX(ke.ident == pid);
+ fprintf(stderr, "fork\n");
+ break;
+ case NOTE_TRACKERR:
+ errx(1, "child tracking failed due to resource shortage");
+ default:
+ errx(1, "kevent returned weird event 0x%x pid %d\n",
+ ke.fflags, (pid_t)ke.ident);
+ }
+ }
+
+ /* Both children now sleeping. */
+
+ ASSX(didchild == didfork == 1);
+
+ kill(pid2, SIGUSR1); /* sync 2.1 */
+ kill(pid, SIGUSR1); /* sync 2 */
+
+ if (wait(&status) < 0)
+ err(1, "wait");
+
+ if (!WIFEXITED(status))
+ errx(1, "child didn't exit?");
+
+ close(kq);
+ return (WEXITSTATUS(status) != 0);
+}
+
+static int
+process_child(void)
+{
+ signal(SIGCHLD, SIG_IGN); /* ignore our children. */
+
+ pause();
+
+ /* fork and see if tracking works. */
+ switch (fork()) {
+ case -1:
+ err(1, "fork");
+ case 0:
+ /* sync 2.1 */
+ pause();
+ execl("/usr/bin/true", "true", NULL);
+ err(1, "execl(true)");
+ }
+
+ /* sync 2 */
+ pause();
+
+ return 0;
+}