#include #include #include #include #include #include #include #include #include int kqsock; #define WATCH_PPROC(proc, data) watch(EVFILT_PROC, proc, data, NOTE_EXIT|NOTE_TRACK, 1) #define WATCH_PROC(proc, data) watch(EVFILT_PROC, proc, data, NOTE_EXIT, 1) #define WATCH_SIG(sig, data) watch(EVFILT_SIGNAL, sig, data, 0, 1) void watch(filter, ident, data, fflags, addrm) short filter; uintptr_t ident; void *data; u_int fflags; int addrm; { struct kevent kev; struct kevent *kptr; int i; kptr = &kev; kev.ident = ident; kev.filter = filter; kev.flags = addrm ? EV_ADD|EV_ENABLE : EV_DELETE|EV_DISABLE; kev.fflags = fflags; kev.udata = data; i = kevent(kqsock, 1, &kptr, 0, NULL, NULL); if (i == -1) warn("kevent"); warnx("kqueue, ident: %d, addrm: %d, ret: %d, data: %p, errno: %s", ident, addrm, i, data, strerror(errno)); } void printch() { printf("got SIGCHLD\n"); fflush(stdout); } int main(int argc, char *argv[]) { struct kevent kqevlist[16]; pid_t pid; int status; int i; int j; int n; char *data; void (*fun)(); if (argc != 2) errx(1, "usage: %s <0|1>", argv[0]); i = atoi(argv[1]); if ((kqsock = kqueue()) == -1) err(1, "kqueue"); WATCH_PPROC(getpid(), getpid()); WATCH_SIG(SIGCHLD, printch); printf("parent: %d\n", getpid()); fflush(stdout); switch((pid = fork())) { case 0: printf("child: %d\n", getpid()); fflush(stdout); exit(0); break; case -1: err(1, "fork"); break; default: break; } /* parent */ if (i) sleep(1); WATCH_PROC(pid, "this is a string"); if ((n = kevent(kqsock, 0, NULL, sizeof kqevlist / sizeof *kqevlist, kqevlist, (struct timespec *)0)) <= 0) { if (n == -1 && errno != EINTR) { err(1, "kevent"); } } for (j = 0; j < n; j++) { if (kqevlist[j].filter == EVFILT_PROC) { data = kqevlist[j].udata; pid = wait4(kqevlist[j].ident, &status, WNOHANG, NULL); if (pid == 0) warnx("pid is zero"); printf("[%d]: exit status 0x%x\n", pid, status); printf("returned: %p: %s\n", data, data); fflush(stdout); } else if (kqevlist[j].filter == EVFILT_SIGNAL) { fun = kqevlist[j].udata; fun(); } else warn("unknown filter: %x", kqevlist[j].filter); } return 0; }