xref: /src/tests/sys/kqueue/libkqueue/proc.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
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