160a396a4SRobert Watson /*
260a396a4SRobert Watson * Copyright (c) 2009 Mark Heily <mark@heily.com>
360a396a4SRobert Watson *
460a396a4SRobert Watson * Permission to use, copy, modify, and distribute this software for any
560a396a4SRobert Watson * purpose with or without fee is hereby granted, provided that the above
660a396a4SRobert Watson * copyright notice and this permission notice appear in all copies.
760a396a4SRobert Watson *
860a396a4SRobert Watson * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
960a396a4SRobert Watson * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1060a396a4SRobert Watson * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1160a396a4SRobert Watson * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1260a396a4SRobert Watson * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1360a396a4SRobert Watson * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1460a396a4SRobert Watson * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1560a396a4SRobert Watson */
1660a396a4SRobert Watson
170136244aSJonathan Anderson #include <sys/stat.h>
180136244aSJonathan Anderson
190136244aSJonathan Anderson #include <err.h>
200136244aSJonathan Anderson
210136244aSJonathan Anderson #include "config.h"
2260a396a4SRobert Watson #include "common.h"
2360a396a4SRobert Watson
2460a396a4SRobert Watson static int sigusr1_caught = 0;
2560a396a4SRobert Watson
2660a396a4SRobert Watson
2760a396a4SRobert Watson static void
sig_handler(__unused int signum)28c9c283bdSAlex Richardson sig_handler(__unused int signum)
2960a396a4SRobert Watson {
3060a396a4SRobert Watson sigusr1_caught = 1;
3160a396a4SRobert Watson }
3260a396a4SRobert Watson
3360a396a4SRobert Watson static void
add_and_delete(void)3460a396a4SRobert Watson add_and_delete(void)
3560a396a4SRobert Watson {
3660a396a4SRobert Watson struct kevent kev;
3760a396a4SRobert Watson pid_t pid;
3860a396a4SRobert Watson
3960a396a4SRobert Watson /* Create a child that waits to be killed and then exits */
4060a396a4SRobert Watson pid = fork();
4160a396a4SRobert Watson if (pid == 0) {
420136244aSJonathan Anderson struct stat s;
43345f2b96SJonathan Anderson if (fstat(kqfd, &s) != -1)
44345f2b96SJonathan Anderson errx(1, "kqueue inherited across fork! (%s() at %s:%d)",
45345f2b96SJonathan Anderson __func__, __FILE__, __LINE__);
460136244aSJonathan Anderson
4760a396a4SRobert Watson pause();
4860a396a4SRobert Watson exit(2);
4960a396a4SRobert Watson }
5060a396a4SRobert Watson printf(" -- child created (pid %d)\n", (int) pid);
5160a396a4SRobert Watson
5260a396a4SRobert Watson test_begin("kevent(EVFILT_PROC, EV_ADD)");
5360a396a4SRobert Watson
5460a396a4SRobert Watson test_no_kevents();
5560a396a4SRobert Watson kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD, 0, 0, NULL);
5660a396a4SRobert Watson test_no_kevents();
5760a396a4SRobert Watson
5860a396a4SRobert Watson success();
5960a396a4SRobert Watson
6060a396a4SRobert Watson test_begin("kevent(EVFILT_PROC, EV_DELETE)");
6160a396a4SRobert Watson
620136244aSJonathan Anderson sleep(1);
6360a396a4SRobert Watson test_no_kevents();
6460a396a4SRobert Watson kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_DELETE, 0, 0, NULL);
6560a396a4SRobert Watson if (kill(pid, SIGKILL) < 0)
6660a396a4SRobert Watson err(1, "kill");
6760a396a4SRobert Watson sleep(1);
6860a396a4SRobert Watson test_no_kevents();
6960a396a4SRobert Watson
7060a396a4SRobert Watson success();
7160a396a4SRobert Watson
7260a396a4SRobert Watson }
7360a396a4SRobert Watson
740e3d6ed4SEric van Gyzen static void
proc_track(int sleep_time)750e3d6ed4SEric van Gyzen proc_track(int sleep_time)
760e3d6ed4SEric van Gyzen {
770e3d6ed4SEric van Gyzen char test_id[64];
780e3d6ed4SEric van Gyzen struct kevent kev;
790e3d6ed4SEric van Gyzen pid_t pid;
800e3d6ed4SEric van Gyzen int pipe_fd[2];
810e3d6ed4SEric van Gyzen ssize_t result;
820e3d6ed4SEric van Gyzen
830e3d6ed4SEric van Gyzen snprintf(test_id, sizeof(test_id),
840e3d6ed4SEric van Gyzen "kevent(EVFILT_PROC, NOTE_TRACK); sleep %d", sleep_time);
850e3d6ed4SEric van Gyzen test_begin(test_id);
860e3d6ed4SEric van Gyzen test_no_kevents();
870e3d6ed4SEric van Gyzen
880e3d6ed4SEric van Gyzen if (pipe(pipe_fd)) {
890e3d6ed4SEric van Gyzen err(1, "pipe (parent) failed! (%s() at %s:%d)",
900e3d6ed4SEric van Gyzen __func__, __FILE__, __LINE__);
910e3d6ed4SEric van Gyzen }
920e3d6ed4SEric van Gyzen
930e3d6ed4SEric van Gyzen /* Create a child to track. */
940e3d6ed4SEric van Gyzen pid = fork();
950e3d6ed4SEric van Gyzen if (pid == 0) { /* Child */
960e3d6ed4SEric van Gyzen pid_t grandchild = -1;
970e3d6ed4SEric van Gyzen
980e3d6ed4SEric van Gyzen /*
990e3d6ed4SEric van Gyzen * Give the parent a chance to start tracking us.
1000e3d6ed4SEric van Gyzen */
1010e3d6ed4SEric van Gyzen result = read(pipe_fd[1], test_id, 1);
1020e3d6ed4SEric van Gyzen if (result != 1) {
1030e3d6ed4SEric van Gyzen err(1, "read from pipe in child failed! (ret %zd) (%s() at %s:%d)",
1040e3d6ed4SEric van Gyzen result, __func__, __FILE__, __LINE__);
1050e3d6ed4SEric van Gyzen }
1060e3d6ed4SEric van Gyzen
1070e3d6ed4SEric van Gyzen /*
1080e3d6ed4SEric van Gyzen * Spawn a grandchild that will immediately exit. If the kernel has bug
1090e3d6ed4SEric van Gyzen * 180385, the parent will see a kevent with both NOTE_CHILD and
1100e3d6ed4SEric van Gyzen * NOTE_EXIT. If that bug is fixed, it will see two separate kevents
1110e3d6ed4SEric van Gyzen * for those notes. Note that this triggers the conditions for
1120e3d6ed4SEric van Gyzen * detecting the bug quite reliably on a 1 CPU system (or if the test
1130e3d6ed4SEric van Gyzen * process is restricted to a single CPU), but may not trigger it on a
1140e3d6ed4SEric van Gyzen * multi-CPU system.
1150e3d6ed4SEric van Gyzen */
1160e3d6ed4SEric van Gyzen grandchild = fork();
1170e3d6ed4SEric van Gyzen if (grandchild == 0) { /* Grandchild */
1180e3d6ed4SEric van Gyzen if (sleep_time) sleep(sleep_time);
1190e3d6ed4SEric van Gyzen exit(1);
1200e3d6ed4SEric van Gyzen } else if (grandchild == -1) { /* Error */
1210e3d6ed4SEric van Gyzen err(1, "fork (grandchild) failed! (%s() at %s:%d)",
1220e3d6ed4SEric van Gyzen __func__, __FILE__, __LINE__);
1230e3d6ed4SEric van Gyzen } else { /* Child (Grandchild Parent) */
1240e3d6ed4SEric van Gyzen printf(" -- grandchild created (pid %d)\n", (int) grandchild);
1250e3d6ed4SEric van Gyzen }
1260e3d6ed4SEric van Gyzen if (sleep_time) sleep(sleep_time);
1270e3d6ed4SEric van Gyzen exit(0);
1280e3d6ed4SEric van Gyzen } else if (pid == -1) { /* Error */
1290e3d6ed4SEric van Gyzen err(1, "fork (child) failed! (%s() at %s:%d)",
1300e3d6ed4SEric van Gyzen __func__, __FILE__, __LINE__);
1310e3d6ed4SEric van Gyzen }
1320e3d6ed4SEric van Gyzen
1330e3d6ed4SEric van Gyzen printf(" -- child created (pid %d)\n", (int) pid);
1340e3d6ed4SEric van Gyzen
1350e3d6ed4SEric van Gyzen kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD | EV_ENABLE,
1360e3d6ed4SEric van Gyzen NOTE_TRACK | NOTE_EXEC | NOTE_EXIT | NOTE_FORK,
1370e3d6ed4SEric van Gyzen 0, NULL);
1380e3d6ed4SEric van Gyzen
1390e3d6ed4SEric van Gyzen printf(" -- tracking child (pid %d)\n", (int) pid);
1400e3d6ed4SEric van Gyzen
1410e3d6ed4SEric van Gyzen /* Now that we're tracking the child, tell it to proceed. */
1420e3d6ed4SEric van Gyzen result = write(pipe_fd[0], test_id, 1);
1430e3d6ed4SEric van Gyzen if (result != 1) {
1440e3d6ed4SEric van Gyzen err(1, "write to pipe in parent failed! (ret %zd) (%s() at %s:%d)",
1450e3d6ed4SEric van Gyzen result, __func__, __FILE__, __LINE__);
1460e3d6ed4SEric van Gyzen }
1470e3d6ed4SEric van Gyzen
1480e3d6ed4SEric van Gyzen /*
1490e3d6ed4SEric van Gyzen * Several events should be received:
1500e3d6ed4SEric van Gyzen * - NOTE_FORK (from child)
1510e3d6ed4SEric van Gyzen * - NOTE_CHILD (from grandchild)
1520e3d6ed4SEric van Gyzen * - NOTE_EXIT (from grandchild)
1530e3d6ed4SEric van Gyzen * - NOTE_EXIT (from child)
1540e3d6ed4SEric van Gyzen *
1550e3d6ed4SEric van Gyzen * The NOTE_FORK and NOTE_EXIT from the child could be combined into a
1560e3d6ed4SEric van Gyzen * single event, but the NOTE_CHILD and NOTE_EXIT from the grandchild must
1570e3d6ed4SEric van Gyzen * not be combined.
1580e3d6ed4SEric van Gyzen *
1590e3d6ed4SEric van Gyzen * The loop continues until no events are received within a 5 second
1600e3d6ed4SEric van Gyzen * period, at which point it is assumed that no more will be coming. The
1610e3d6ed4SEric van Gyzen * loop is deliberately designed to attempt to get events even after all
1620e3d6ed4SEric van Gyzen * the expected ones are received in case some spurious events are
1630e3d6ed4SEric van Gyzen * generated as well as the expected ones.
1640e3d6ed4SEric van Gyzen */
1650e3d6ed4SEric van Gyzen {
1660e3d6ed4SEric van Gyzen int child_exit = 0;
1670e3d6ed4SEric van Gyzen int child_fork = 0;
1680e3d6ed4SEric van Gyzen int gchild_exit = 0;
1690e3d6ed4SEric van Gyzen int gchild_note = 0;
1700e3d6ed4SEric van Gyzen pid_t gchild_pid = -1;
1710e3d6ed4SEric van Gyzen int done = 0;
17253e992cfSDavid Bright char *kev_str;
1730e3d6ed4SEric van Gyzen
1740e3d6ed4SEric van Gyzen while (!done)
1750e3d6ed4SEric van Gyzen {
1760e3d6ed4SEric van Gyzen int handled = 0;
1770e3d6ed4SEric van Gyzen struct kevent *kevp;
1780e3d6ed4SEric van Gyzen
1790e3d6ed4SEric van Gyzen kevp = kevent_get_timeout(kqfd, 5);
1800e3d6ed4SEric van Gyzen if (kevp == NULL) {
1810e3d6ed4SEric van Gyzen done = 1;
1820e3d6ed4SEric van Gyzen } else {
18353e992cfSDavid Bright kev_str = kevent_to_str(kevp);
18453e992cfSDavid Bright printf(" -- Received kevent: %s\n", kev_str);
18553e992cfSDavid Bright free(kev_str);
1860e3d6ed4SEric van Gyzen
1870e3d6ed4SEric van Gyzen if ((kevp->fflags & NOTE_CHILD) && (kevp->fflags & NOTE_EXIT)) {
1880e3d6ed4SEric van Gyzen errx(1, "NOTE_CHILD and NOTE_EXIT in same kevent: %s", kevent_to_str(kevp));
1890e3d6ed4SEric van Gyzen }
1900e3d6ed4SEric van Gyzen
1910e3d6ed4SEric van Gyzen if (kevp->fflags & NOTE_CHILD) {
1920e3d6ed4SEric van Gyzen if (kevp->data == pid) {
1930e3d6ed4SEric van Gyzen if (!gchild_note) {
1940e3d6ed4SEric van Gyzen ++gchild_note;
1950e3d6ed4SEric van Gyzen gchild_pid = kevp->ident;
1960e3d6ed4SEric van Gyzen ++handled;
1970e3d6ed4SEric van Gyzen } else {
1980e3d6ed4SEric van Gyzen errx(1, "Spurious NOTE_CHILD: %s", kevent_to_str(kevp));
1990e3d6ed4SEric van Gyzen }
2000e3d6ed4SEric van Gyzen }
2010e3d6ed4SEric van Gyzen }
2020e3d6ed4SEric van Gyzen
2030e3d6ed4SEric van Gyzen if (kevp->fflags & NOTE_EXIT) {
204c9c283bdSAlex Richardson if ((kevp->ident == (uintptr_t)pid) && (!child_exit)) {
2050e3d6ed4SEric van Gyzen ++child_exit;
2060e3d6ed4SEric van Gyzen ++handled;
207c9c283bdSAlex Richardson } else if ((kevp->ident == (uintptr_t)gchild_pid) && (!gchild_exit)) {
2080e3d6ed4SEric van Gyzen ++gchild_exit;
2090e3d6ed4SEric van Gyzen ++handled;
2100e3d6ed4SEric van Gyzen } else {
2110e3d6ed4SEric van Gyzen errx(1, "Spurious NOTE_EXIT: %s", kevent_to_str(kevp));
2120e3d6ed4SEric van Gyzen }
2130e3d6ed4SEric van Gyzen }
2140e3d6ed4SEric van Gyzen
2150e3d6ed4SEric van Gyzen if (kevp->fflags & NOTE_FORK) {
216c9c283bdSAlex Richardson if ((kevp->ident == (uintptr_t)pid) && (!child_fork)) {
2170e3d6ed4SEric van Gyzen ++child_fork;
2180e3d6ed4SEric van Gyzen ++handled;
2190e3d6ed4SEric van Gyzen } else {
2200e3d6ed4SEric van Gyzen errx(1, "Spurious NOTE_FORK: %s", kevent_to_str(kevp));
2210e3d6ed4SEric van Gyzen }
2220e3d6ed4SEric van Gyzen }
2230e3d6ed4SEric van Gyzen
2240e3d6ed4SEric van Gyzen if (!handled) {
2250e3d6ed4SEric van Gyzen errx(1, "Spurious kevent: %s", kevent_to_str(kevp));
2260e3d6ed4SEric van Gyzen }
2270e3d6ed4SEric van Gyzen
2280e3d6ed4SEric van Gyzen free(kevp);
2290e3d6ed4SEric van Gyzen }
2300e3d6ed4SEric van Gyzen }
2310e3d6ed4SEric van Gyzen
2320e3d6ed4SEric van Gyzen /* Make sure all expected events were received. */
2330e3d6ed4SEric van Gyzen if (child_exit && child_fork && gchild_exit && gchild_note) {
2340e3d6ed4SEric van Gyzen printf(" -- Received all expected events.\n");
2350e3d6ed4SEric van Gyzen } else {
2360e3d6ed4SEric van Gyzen errx(1, "Did not receive all expected events.");
2370e3d6ed4SEric van Gyzen }
2380e3d6ed4SEric van Gyzen }
2390e3d6ed4SEric van Gyzen
2400e3d6ed4SEric van Gyzen success();
2410e3d6ed4SEric van Gyzen }
2420e3d6ed4SEric van Gyzen
2430136244aSJonathan Anderson #ifdef TODO
24460a396a4SRobert Watson static void
event_trigger(void)24560a396a4SRobert Watson event_trigger(void)
24660a396a4SRobert Watson {
24760a396a4SRobert Watson struct kevent kev;
24860a396a4SRobert Watson pid_t pid;
24960a396a4SRobert Watson
25060a396a4SRobert Watson test_begin("kevent(EVFILT_PROC, wait)");
25160a396a4SRobert Watson
25260a396a4SRobert Watson /* Create a child that waits to be killed and then exits */
25360a396a4SRobert Watson pid = fork();
25460a396a4SRobert Watson if (pid == 0) {
25560a396a4SRobert Watson pause();
25660a396a4SRobert Watson printf(" -- child caught signal, exiting\n");
25760a396a4SRobert Watson exit(2);
25860a396a4SRobert Watson }
25960a396a4SRobert Watson printf(" -- child created (pid %d)\n", (int) pid);
26060a396a4SRobert Watson
26160a396a4SRobert Watson test_no_kevents();
26260a396a4SRobert Watson kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD, 0, 0, NULL);
26360a396a4SRobert Watson
26460a396a4SRobert Watson /* Cause the child to exit, then retrieve the event */
26560a396a4SRobert Watson printf(" -- killing process %d\n", (int) pid);
26660a396a4SRobert Watson if (kill(pid, SIGUSR1) < 0)
26760a396a4SRobert Watson err(1, "kill");
26860a396a4SRobert Watson kevent_cmp(&kev, kevent_get(kqfd));
26960a396a4SRobert Watson test_no_kevents();
27060a396a4SRobert Watson
27160a396a4SRobert Watson success();
27260a396a4SRobert Watson }
27360a396a4SRobert Watson
274c9c283bdSAlex Richardson static void
test_kevent_signal_disable(void)27560a396a4SRobert Watson test_kevent_signal_disable(void)
27660a396a4SRobert Watson {
27760a396a4SRobert Watson const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)";
27860a396a4SRobert Watson struct kevent kev;
27960a396a4SRobert Watson
28060a396a4SRobert Watson test_begin(test_id);
28160a396a4SRobert Watson
28260a396a4SRobert Watson EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL);
28360a396a4SRobert Watson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
28460a396a4SRobert Watson err(1, "%s", test_id);
28560a396a4SRobert Watson
28660a396a4SRobert Watson /* Block SIGUSR1, then send it to ourselves */
28760a396a4SRobert Watson sigset_t mask;
28860a396a4SRobert Watson sigemptyset(&mask);
28960a396a4SRobert Watson sigaddset(&mask, SIGUSR1);
29060a396a4SRobert Watson if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
29160a396a4SRobert Watson err(1, "sigprocmask");
29260a396a4SRobert Watson if (kill(getpid(), SIGKILL) < 0)
29360a396a4SRobert Watson err(1, "kill");
29460a396a4SRobert Watson
29560a396a4SRobert Watson test_no_kevents();
29660a396a4SRobert Watson
29760a396a4SRobert Watson success();
29860a396a4SRobert Watson }
29960a396a4SRobert Watson
30060a396a4SRobert Watson void
test_kevent_signal_enable(void)30160a396a4SRobert Watson test_kevent_signal_enable(void)
30260a396a4SRobert Watson {
30360a396a4SRobert Watson const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)";
30460a396a4SRobert Watson struct kevent kev;
30560a396a4SRobert Watson
30660a396a4SRobert Watson test_begin(test_id);
30760a396a4SRobert Watson
30860a396a4SRobert Watson EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL);
30960a396a4SRobert Watson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
31060a396a4SRobert Watson err(1, "%s", test_id);
31160a396a4SRobert Watson
31260a396a4SRobert Watson /* Block SIGUSR1, then send it to ourselves */
31360a396a4SRobert Watson sigset_t mask;
31460a396a4SRobert Watson sigemptyset(&mask);
31560a396a4SRobert Watson sigaddset(&mask, SIGUSR1);
31660a396a4SRobert Watson if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
31760a396a4SRobert Watson err(1, "sigprocmask");
31860a396a4SRobert Watson if (kill(getpid(), SIGUSR1) < 0)
31960a396a4SRobert Watson err(1, "kill");
32060a396a4SRobert Watson
32160a396a4SRobert Watson kev.flags = EV_ADD | EV_CLEAR;
32260a396a4SRobert Watson #if LIBKQUEUE
32360a396a4SRobert Watson kev.data = 1; /* WORKAROUND */
32460a396a4SRobert Watson #else
32560a396a4SRobert Watson kev.data = 2; // one extra time from test_kevent_signal_disable()
32660a396a4SRobert Watson #endif
32760a396a4SRobert Watson kevent_cmp(&kev, kevent_get(kqfd));
32860a396a4SRobert Watson
32960a396a4SRobert Watson /* Delete the watch */
33060a396a4SRobert Watson kev.flags = EV_DELETE;
33160a396a4SRobert Watson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
33260a396a4SRobert Watson err(1, "%s", test_id);
33360a396a4SRobert Watson
33460a396a4SRobert Watson success();
33560a396a4SRobert Watson }
33660a396a4SRobert Watson
33760a396a4SRobert Watson void
test_kevent_signal_del(void)33860a396a4SRobert Watson test_kevent_signal_del(void)
33960a396a4SRobert Watson {
34060a396a4SRobert Watson const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)";
34160a396a4SRobert Watson struct kevent kev;
34260a396a4SRobert Watson
34360a396a4SRobert Watson test_begin(test_id);
34460a396a4SRobert Watson
34560a396a4SRobert Watson /* Delete the kevent */
34660a396a4SRobert Watson EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL);
34760a396a4SRobert Watson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
34860a396a4SRobert Watson err(1, "%s", test_id);
34960a396a4SRobert Watson
35060a396a4SRobert Watson /* Block SIGUSR1, then send it to ourselves */
35160a396a4SRobert Watson sigset_t mask;
35260a396a4SRobert Watson sigemptyset(&mask);
35360a396a4SRobert Watson sigaddset(&mask, SIGUSR1);
35460a396a4SRobert Watson if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
35560a396a4SRobert Watson err(1, "sigprocmask");
35660a396a4SRobert Watson if (kill(getpid(), SIGUSR1) < 0)
35760a396a4SRobert Watson err(1, "kill");
35860a396a4SRobert Watson
35960a396a4SRobert Watson test_no_kevents();
36060a396a4SRobert Watson success();
36160a396a4SRobert Watson }
36260a396a4SRobert Watson
36360a396a4SRobert Watson void
test_kevent_signal_oneshot(void)36460a396a4SRobert Watson test_kevent_signal_oneshot(void)
36560a396a4SRobert Watson {
36660a396a4SRobert Watson const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)";
36760a396a4SRobert Watson struct kevent kev;
36860a396a4SRobert Watson
36960a396a4SRobert Watson test_begin(test_id);
37060a396a4SRobert Watson
37160a396a4SRobert Watson EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL);
37260a396a4SRobert Watson if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
37360a396a4SRobert Watson err(1, "%s", test_id);
37460a396a4SRobert Watson
37560a396a4SRobert Watson /* Block SIGUSR1, then send it to ourselves */
37660a396a4SRobert Watson sigset_t mask;
37760a396a4SRobert Watson sigemptyset(&mask);
37860a396a4SRobert Watson sigaddset(&mask, SIGUSR1);
37960a396a4SRobert Watson if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
38060a396a4SRobert Watson err(1, "sigprocmask");
38160a396a4SRobert Watson if (kill(getpid(), SIGUSR1) < 0)
38260a396a4SRobert Watson err(1, "kill");
38360a396a4SRobert Watson
38460a396a4SRobert Watson kev.flags |= EV_CLEAR;
38560a396a4SRobert Watson kev.data = 1;
38660a396a4SRobert Watson kevent_cmp(&kev, kevent_get(kqfd));
38760a396a4SRobert Watson
38860a396a4SRobert Watson /* Send another one and make sure we get no events */
38960a396a4SRobert Watson if (kill(getpid(), SIGUSR1) < 0)
39060a396a4SRobert Watson err(1, "kill");
39160a396a4SRobert Watson test_no_kevents();
39260a396a4SRobert Watson
39360a396a4SRobert Watson success();
39460a396a4SRobert Watson }
39560a396a4SRobert Watson #endif
39660a396a4SRobert Watson
39760a396a4SRobert Watson void
test_evfilt_proc(void)398c9c283bdSAlex Richardson test_evfilt_proc(void)
39960a396a4SRobert Watson {
40060a396a4SRobert Watson kqfd = kqueue();
40160a396a4SRobert Watson
40260a396a4SRobert Watson signal(SIGUSR1, sig_handler);
40360a396a4SRobert Watson
40460a396a4SRobert Watson add_and_delete();
4050e3d6ed4SEric van Gyzen proc_track(0); /* Run without sleeping before children exit. */
4060e3d6ed4SEric van Gyzen proc_track(1); /* Sleep a bit in the children before exiting. */
4070136244aSJonathan Anderson
4080136244aSJonathan Anderson #if TODO
40960a396a4SRobert Watson event_trigger();
4100136244aSJonathan Anderson #endif
41160a396a4SRobert Watson
41260a396a4SRobert Watson signal(SIGUSR1, SIG_DFL);
41360a396a4SRobert Watson
41460a396a4SRobert Watson #if TODO
41560a396a4SRobert Watson test_kevent_signal_add();
41660a396a4SRobert Watson test_kevent_signal_del();
41760a396a4SRobert Watson test_kevent_signal_get();
41860a396a4SRobert Watson test_kevent_signal_disable();
41960a396a4SRobert Watson test_kevent_signal_enable();
42060a396a4SRobert Watson test_kevent_signal_oneshot();
42160a396a4SRobert Watson #endif
42260a396a4SRobert Watson close(kqfd);
42360a396a4SRobert Watson }
424