diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2002-03-02 21:48:06 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2002-03-02 21:48:06 +0000 |
commit | 16a72cc1001be69b5793f563e912d3dbceed871d (patch) | |
tree | ed19b3cdabaa0b7409757ae53345e8eb950cf76f /regress/sys/kern/kqueue/kqueue-process.c | |
parent | 4c655c8762a5d63e4253d66a151de24a93c96120 (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.c | 133 |
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; +} |