xref: /freebsd-12.1/tests/sys/kqueue/libkqueue/proc.c (revision 90e4ba11)
1cb5fe245SEnji Cooper /*
2cb5fe245SEnji Cooper  * Copyright (c) 2009 Mark Heily <[email protected]>
3cb5fe245SEnji Cooper  *
4cb5fe245SEnji Cooper  * Permission to use, copy, modify, and distribute this software for any
5cb5fe245SEnji Cooper  * purpose with or without fee is hereby granted, provided that the above
6cb5fe245SEnji Cooper  * copyright notice and this permission notice appear in all copies.
7cb5fe245SEnji Cooper  *
8cb5fe245SEnji Cooper  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9cb5fe245SEnji Cooper  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10cb5fe245SEnji Cooper  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11cb5fe245SEnji Cooper  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12cb5fe245SEnji Cooper  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13cb5fe245SEnji Cooper  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14cb5fe245SEnji Cooper  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15cb5fe245SEnji Cooper  *
16cb5fe245SEnji Cooper  * $FreeBSD$
17cb5fe245SEnji Cooper  */
18cb5fe245SEnji Cooper 
19cb5fe245SEnji Cooper #include <sys/stat.h>
20cb5fe245SEnji Cooper 
21cb5fe245SEnji Cooper #include <err.h>
22cb5fe245SEnji Cooper 
23cb5fe245SEnji Cooper #include "config.h"
24cb5fe245SEnji Cooper #include "common.h"
25cb5fe245SEnji Cooper 
26cb5fe245SEnji Cooper static int sigusr1_caught = 0;
27cb5fe245SEnji Cooper 
28cb5fe245SEnji Cooper int kqfd;
29cb5fe245SEnji Cooper 
30cb5fe245SEnji Cooper static void
sig_handler(int signum)31cb5fe245SEnji Cooper sig_handler(int signum)
32cb5fe245SEnji Cooper {
33cb5fe245SEnji Cooper     sigusr1_caught = 1;
34cb5fe245SEnji Cooper }
35cb5fe245SEnji Cooper 
36cb5fe245SEnji Cooper static void
add_and_delete(void)37cb5fe245SEnji Cooper add_and_delete(void)
38cb5fe245SEnji Cooper {
39cb5fe245SEnji Cooper     struct kevent kev;
40cb5fe245SEnji Cooper     pid_t pid;
41cb5fe245SEnji Cooper 
42cb5fe245SEnji Cooper     /* Create a child that waits to be killed and then exits */
43cb5fe245SEnji Cooper     pid = fork();
44cb5fe245SEnji Cooper     if (pid == 0) {
45cb5fe245SEnji Cooper         struct stat s;
46cb5fe245SEnji Cooper         if (fstat(kqfd, &s) != -1)
47cb5fe245SEnji Cooper             errx(1, "kqueue inherited across fork! (%s() at %s:%d)",
48cb5fe245SEnji Cooper                 __func__, __FILE__, __LINE__);
49cb5fe245SEnji Cooper 
50cb5fe245SEnji Cooper         pause();
51cb5fe245SEnji Cooper         exit(2);
52cb5fe245SEnji Cooper     }
53cb5fe245SEnji Cooper     printf(" -- child created (pid %d)\n", (int) pid);
54cb5fe245SEnji Cooper 
55cb5fe245SEnji Cooper     test_begin("kevent(EVFILT_PROC, EV_ADD)");
56cb5fe245SEnji Cooper 
57cb5fe245SEnji Cooper     test_no_kevents();
58cb5fe245SEnji Cooper     kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD, 0, 0, NULL);
59cb5fe245SEnji Cooper     test_no_kevents();
60cb5fe245SEnji Cooper 
61cb5fe245SEnji Cooper     success();
62cb5fe245SEnji Cooper 
63cb5fe245SEnji Cooper     test_begin("kevent(EVFILT_PROC, EV_DELETE)");
64cb5fe245SEnji Cooper 
65cb5fe245SEnji Cooper     sleep(1);
66cb5fe245SEnji Cooper     test_no_kevents();
67cb5fe245SEnji Cooper     kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_DELETE, 0, 0, NULL);
68cb5fe245SEnji Cooper     if (kill(pid, SIGKILL) < 0)
69cb5fe245SEnji Cooper         err(1, "kill");
70cb5fe245SEnji Cooper     sleep(1);
71cb5fe245SEnji Cooper     test_no_kevents();
72cb5fe245SEnji Cooper 
73cb5fe245SEnji Cooper     success();
74cb5fe245SEnji Cooper 
75cb5fe245SEnji Cooper }
76cb5fe245SEnji Cooper 
77cb5fe245SEnji Cooper static void
proc_track(int sleep_time)78cb5fe245SEnji Cooper proc_track(int sleep_time)
79cb5fe245SEnji Cooper {
80cb5fe245SEnji Cooper     char test_id[64];
81cb5fe245SEnji Cooper     struct kevent kev;
82cb5fe245SEnji Cooper     pid_t pid;
83cb5fe245SEnji Cooper     int pipe_fd[2];
84cb5fe245SEnji Cooper     ssize_t result;
85cb5fe245SEnji Cooper 
86cb5fe245SEnji Cooper     snprintf(test_id, sizeof(test_id),
87cb5fe245SEnji Cooper              "kevent(EVFILT_PROC, NOTE_TRACK); sleep %d", sleep_time);
88cb5fe245SEnji Cooper     test_begin(test_id);
89cb5fe245SEnji Cooper     test_no_kevents();
90cb5fe245SEnji Cooper 
91cb5fe245SEnji Cooper     if (pipe(pipe_fd)) {
92cb5fe245SEnji Cooper         err(1, "pipe (parent) failed! (%s() at %s:%d)",
93cb5fe245SEnji Cooper             __func__, __FILE__, __LINE__);
94cb5fe245SEnji Cooper     }
95cb5fe245SEnji Cooper 
96cb5fe245SEnji Cooper     /* Create a child to track. */
97cb5fe245SEnji Cooper     pid = fork();
98cb5fe245SEnji Cooper     if (pid == 0) { /* Child */
99cb5fe245SEnji Cooper         pid_t grandchild = -1;
100cb5fe245SEnji Cooper 
101cb5fe245SEnji Cooper         /*
102cb5fe245SEnji Cooper          * Give the parent a chance to start tracking us.
103cb5fe245SEnji Cooper          */
104cb5fe245SEnji Cooper         result = read(pipe_fd[1], test_id, 1);
105cb5fe245SEnji Cooper         if (result != 1) {
106cb5fe245SEnji Cooper             err(1, "read from pipe in child failed! (ret %zd) (%s() at %s:%d)",
107cb5fe245SEnji Cooper                 result, __func__, __FILE__, __LINE__);
108cb5fe245SEnji Cooper         }
109cb5fe245SEnji Cooper 
110cb5fe245SEnji Cooper         /*
111cb5fe245SEnji Cooper          * Spawn a grandchild that will immediately exit. If the kernel has bug
112cb5fe245SEnji Cooper          * 180385, the parent will see a kevent with both NOTE_CHILD and
113cb5fe245SEnji Cooper          * NOTE_EXIT. If that bug is fixed, it will see two separate kevents
114cb5fe245SEnji Cooper          * for those notes. Note that this triggers the conditions for
115cb5fe245SEnji Cooper          * detecting the bug quite reliably on a 1 CPU system (or if the test
116cb5fe245SEnji Cooper          * process is restricted to a single CPU), but may not trigger it on a
117cb5fe245SEnji Cooper          * multi-CPU system.
118cb5fe245SEnji Cooper          */
119cb5fe245SEnji Cooper         grandchild = fork();
120cb5fe245SEnji Cooper         if (grandchild == 0) { /* Grandchild */
121cb5fe245SEnji Cooper             if (sleep_time) sleep(sleep_time);
122cb5fe245SEnji Cooper             exit(1);
123cb5fe245SEnji Cooper         } else if (grandchild == -1) { /* Error */
124cb5fe245SEnji Cooper             err(1, "fork (grandchild) failed! (%s() at %s:%d)",
125cb5fe245SEnji Cooper                 __func__, __FILE__, __LINE__);
126cb5fe245SEnji Cooper         } else { /* Child (Grandchild Parent) */
127cb5fe245SEnji Cooper             printf(" -- grandchild created (pid %d)\n", (int) grandchild);
128cb5fe245SEnji Cooper         }
129cb5fe245SEnji Cooper         if (sleep_time) sleep(sleep_time);
130cb5fe245SEnji Cooper         exit(0);
131cb5fe245SEnji Cooper     } else if (pid == -1) { /* Error */
132cb5fe245SEnji Cooper         err(1, "fork (child) failed! (%s() at %s:%d)",
133cb5fe245SEnji Cooper             __func__, __FILE__, __LINE__);
134cb5fe245SEnji Cooper     }
135cb5fe245SEnji Cooper 
136cb5fe245SEnji Cooper     printf(" -- child created (pid %d)\n", (int) pid);
137cb5fe245SEnji Cooper 
138cb5fe245SEnji Cooper     kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD | EV_ENABLE,
139cb5fe245SEnji Cooper                NOTE_TRACK | NOTE_EXEC | NOTE_EXIT | NOTE_FORK,
140cb5fe245SEnji Cooper                0, NULL);
141cb5fe245SEnji Cooper 
142cb5fe245SEnji Cooper     printf(" -- tracking child (pid %d)\n", (int) pid);
143cb5fe245SEnji Cooper 
144cb5fe245SEnji Cooper     /* Now that we're tracking the child, tell it to proceed. */
145cb5fe245SEnji Cooper     result = write(pipe_fd[0], test_id, 1);
146cb5fe245SEnji Cooper     if (result != 1) {
147cb5fe245SEnji Cooper         err(1, "write to pipe in parent failed! (ret %zd) (%s() at %s:%d)",
148cb5fe245SEnji Cooper             result, __func__, __FILE__, __LINE__);
149cb5fe245SEnji Cooper     }
150cb5fe245SEnji Cooper 
151cb5fe245SEnji Cooper     /*
152cb5fe245SEnji Cooper      * Several events should be received:
153cb5fe245SEnji Cooper      *  - NOTE_FORK (from child)
154cb5fe245SEnji Cooper      *  - NOTE_CHILD (from grandchild)
155cb5fe245SEnji Cooper      *  - NOTE_EXIT (from grandchild)
156cb5fe245SEnji Cooper      *  - NOTE_EXIT (from child)
157cb5fe245SEnji Cooper      *
158cb5fe245SEnji Cooper      * The NOTE_FORK and NOTE_EXIT from the child could be combined into a
159cb5fe245SEnji Cooper      * single event, but the NOTE_CHILD and NOTE_EXIT from the grandchild must
160cb5fe245SEnji Cooper      * not be combined.
161cb5fe245SEnji Cooper      *
162cb5fe245SEnji Cooper      * The loop continues until no events are received within a 5 second
163cb5fe245SEnji Cooper      * period, at which point it is assumed that no more will be coming. The
164cb5fe245SEnji Cooper      * loop is deliberately designed to attempt to get events even after all
165cb5fe245SEnji Cooper      * the expected ones are received in case some spurious events are
166cb5fe245SEnji Cooper      * generated as well as the expected ones.
167cb5fe245SEnji Cooper      */
168cb5fe245SEnji Cooper     {
169cb5fe245SEnji Cooper         int child_exit = 0;
170cb5fe245SEnji Cooper         int child_fork = 0;
171cb5fe245SEnji Cooper         int gchild_exit = 0;
172cb5fe245SEnji Cooper         int gchild_note = 0;
173cb5fe245SEnji Cooper         pid_t gchild_pid = -1;
174cb5fe245SEnji Cooper         int done = 0;
175*53e992cfSDavid Bright         char *kev_str;
176cb5fe245SEnji Cooper 
177cb5fe245SEnji Cooper         while (!done)
178cb5fe245SEnji Cooper         {
179cb5fe245SEnji Cooper             int handled = 0;
180cb5fe245SEnji Cooper             struct kevent *kevp;
181cb5fe245SEnji Cooper 
182cb5fe245SEnji Cooper             kevp = kevent_get_timeout(kqfd, 5);
183cb5fe245SEnji Cooper             if (kevp == NULL) {
184cb5fe245SEnji Cooper                 done = 1;
185cb5fe245SEnji Cooper             } else {
186*53e992cfSDavid Bright                 kev_str = kevent_to_str(kevp);
187*53e992cfSDavid Bright                 printf(" -- Received kevent: %s\n", kev_str);
188*53e992cfSDavid Bright                 free(kev_str);
189cb5fe245SEnji Cooper 
190cb5fe245SEnji Cooper                 if ((kevp->fflags & NOTE_CHILD) && (kevp->fflags & NOTE_EXIT)) {
191cb5fe245SEnji Cooper                     errx(1, "NOTE_CHILD and NOTE_EXIT in same kevent: %s", kevent_to_str(kevp));
192cb5fe245SEnji Cooper                 }
193cb5fe245SEnji Cooper 
194cb5fe245SEnji Cooper                 if (kevp->fflags & NOTE_CHILD) {
195cb5fe245SEnji Cooper                     if (kevp->data == pid) {
196cb5fe245SEnji Cooper                         if (!gchild_note) {
197cb5fe245SEnji Cooper                             ++gchild_note;
198cb5fe245SEnji Cooper                             gchild_pid = kevp->ident;
199cb5fe245SEnji Cooper                             ++handled;
200cb5fe245SEnji Cooper                         } else {
201cb5fe245SEnji Cooper                             errx(1, "Spurious NOTE_CHILD: %s", kevent_to_str(kevp));
202cb5fe245SEnji Cooper                         }
203cb5fe245SEnji Cooper                     }
204cb5fe245SEnji Cooper                 }
205cb5fe245SEnji Cooper 
206cb5fe245SEnji Cooper                 if (kevp->fflags & NOTE_EXIT) {
207cb5fe245SEnji Cooper                     if ((kevp->ident == pid) && (!child_exit)) {
208cb5fe245SEnji Cooper                         ++child_exit;
209cb5fe245SEnji Cooper                         ++handled;
210cb5fe245SEnji Cooper                     } else if ((kevp->ident == gchild_pid) && (!gchild_exit)) {
211cb5fe245SEnji Cooper                         ++gchild_exit;
212cb5fe245SEnji Cooper                         ++handled;
213cb5fe245SEnji Cooper                     } else {
214cb5fe245SEnji Cooper                         errx(1, "Spurious NOTE_EXIT: %s", kevent_to_str(kevp));
215cb5fe245SEnji Cooper                     }
216cb5fe245SEnji Cooper                 }
217cb5fe245SEnji Cooper 
218cb5fe245SEnji Cooper                 if (kevp->fflags & NOTE_FORK) {
219cb5fe245SEnji Cooper                     if ((kevp->ident == pid) && (!child_fork)) {
220cb5fe245SEnji Cooper                         ++child_fork;
221cb5fe245SEnji Cooper                         ++handled;
222cb5fe245SEnji Cooper                     } else {
223cb5fe245SEnji Cooper                         errx(1, "Spurious NOTE_FORK: %s", kevent_to_str(kevp));
224cb5fe245SEnji Cooper                     }
225cb5fe245SEnji Cooper                 }
226cb5fe245SEnji Cooper 
227cb5fe245SEnji Cooper                 if (!handled) {
228cb5fe245SEnji Cooper                     errx(1, "Spurious kevent: %s", kevent_to_str(kevp));
229cb5fe245SEnji Cooper                 }
230cb5fe245SEnji Cooper 
231cb5fe245SEnji Cooper                 free(kevp);
232cb5fe245SEnji Cooper             }
233cb5fe245SEnji Cooper         }
234cb5fe245SEnji Cooper 
235cb5fe245SEnji Cooper         /* Make sure all expected events were received. */
236cb5fe245SEnji Cooper         if (child_exit && child_fork && gchild_exit && gchild_note) {
237cb5fe245SEnji Cooper             printf(" -- Received all expected events.\n");
238cb5fe245SEnji Cooper         } else {
239cb5fe245SEnji Cooper             errx(1, "Did not receive all expected events.");
240cb5fe245SEnji Cooper         }
241cb5fe245SEnji Cooper     }
242cb5fe245SEnji Cooper 
243cb5fe245SEnji Cooper     success();
244cb5fe245SEnji Cooper }
245cb5fe245SEnji Cooper 
246cb5fe245SEnji Cooper #ifdef TODO
247cb5fe245SEnji Cooper static void
event_trigger(void)248cb5fe245SEnji Cooper event_trigger(void)
249cb5fe245SEnji Cooper {
250cb5fe245SEnji Cooper     struct kevent kev;
251cb5fe245SEnji Cooper     pid_t pid;
252cb5fe245SEnji Cooper 
253cb5fe245SEnji Cooper     test_begin("kevent(EVFILT_PROC, wait)");
254cb5fe245SEnji Cooper 
255cb5fe245SEnji Cooper     /* Create a child that waits to be killed and then exits */
256cb5fe245SEnji Cooper     pid = fork();
257cb5fe245SEnji Cooper     if (pid == 0) {
258cb5fe245SEnji Cooper         pause();
259cb5fe245SEnji Cooper         printf(" -- child caught signal, exiting\n");
260cb5fe245SEnji Cooper         exit(2);
261cb5fe245SEnji Cooper     }
262cb5fe245SEnji Cooper     printf(" -- child created (pid %d)\n", (int) pid);
263cb5fe245SEnji Cooper 
264cb5fe245SEnji Cooper     test_no_kevents();
265cb5fe245SEnji Cooper     kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD, 0, 0, NULL);
266cb5fe245SEnji Cooper 
267cb5fe245SEnji Cooper     /* Cause the child to exit, then retrieve the event */
268cb5fe245SEnji Cooper     printf(" -- killing process %d\n", (int) pid);
269cb5fe245SEnji Cooper     if (kill(pid, SIGUSR1) < 0)
270cb5fe245SEnji Cooper         err(1, "kill");
271cb5fe245SEnji Cooper     kevent_cmp(&kev, kevent_get(kqfd));
272cb5fe245SEnji Cooper     test_no_kevents();
273cb5fe245SEnji Cooper 
274cb5fe245SEnji Cooper     success();
275cb5fe245SEnji Cooper }
276cb5fe245SEnji Cooper 
277cb5fe245SEnji Cooper void
test_kevent_signal_disable(void)278cb5fe245SEnji Cooper test_kevent_signal_disable(void)
279cb5fe245SEnji Cooper {
280cb5fe245SEnji Cooper     const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)";
281cb5fe245SEnji Cooper     struct kevent kev;
282cb5fe245SEnji Cooper 
283cb5fe245SEnji Cooper     test_begin(test_id);
284cb5fe245SEnji Cooper 
285cb5fe245SEnji Cooper     EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL);
286cb5fe245SEnji Cooper     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
287cb5fe245SEnji Cooper         err(1, "%s", test_id);
288cb5fe245SEnji Cooper 
289cb5fe245SEnji Cooper     /* Block SIGUSR1, then send it to ourselves */
290cb5fe245SEnji Cooper     sigset_t mask;
291cb5fe245SEnji Cooper     sigemptyset(&mask);
292cb5fe245SEnji Cooper     sigaddset(&mask, SIGUSR1);
293cb5fe245SEnji Cooper     if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
294cb5fe245SEnji Cooper         err(1, "sigprocmask");
295cb5fe245SEnji Cooper     if (kill(getpid(), SIGKILL) < 0)
296cb5fe245SEnji Cooper         err(1, "kill");
297cb5fe245SEnji Cooper 
298cb5fe245SEnji Cooper     test_no_kevents();
299cb5fe245SEnji Cooper 
300cb5fe245SEnji Cooper     success();
301cb5fe245SEnji Cooper }
302cb5fe245SEnji Cooper 
303cb5fe245SEnji Cooper void
test_kevent_signal_enable(void)304cb5fe245SEnji Cooper test_kevent_signal_enable(void)
305cb5fe245SEnji Cooper {
306cb5fe245SEnji Cooper     const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)";
307cb5fe245SEnji Cooper     struct kevent kev;
308cb5fe245SEnji Cooper 
309cb5fe245SEnji Cooper     test_begin(test_id);
310cb5fe245SEnji Cooper 
311cb5fe245SEnji Cooper     EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL);
312cb5fe245SEnji Cooper     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
313cb5fe245SEnji Cooper         err(1, "%s", test_id);
314cb5fe245SEnji Cooper 
315cb5fe245SEnji Cooper     /* Block SIGUSR1, then send it to ourselves */
316cb5fe245SEnji Cooper     sigset_t mask;
317cb5fe245SEnji Cooper     sigemptyset(&mask);
318cb5fe245SEnji Cooper     sigaddset(&mask, SIGUSR1);
319cb5fe245SEnji Cooper     if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
320cb5fe245SEnji Cooper         err(1, "sigprocmask");
321cb5fe245SEnji Cooper     if (kill(getpid(), SIGUSR1) < 0)
322cb5fe245SEnji Cooper         err(1, "kill");
323cb5fe245SEnji Cooper 
324cb5fe245SEnji Cooper     kev.flags = EV_ADD | EV_CLEAR;
325cb5fe245SEnji Cooper #if LIBKQUEUE
326cb5fe245SEnji Cooper     kev.data = 1; /* WORKAROUND */
327cb5fe245SEnji Cooper #else
328cb5fe245SEnji Cooper     kev.data = 2; // one extra time from test_kevent_signal_disable()
329cb5fe245SEnji Cooper #endif
330cb5fe245SEnji Cooper     kevent_cmp(&kev, kevent_get(kqfd));
331cb5fe245SEnji Cooper 
332cb5fe245SEnji Cooper     /* Delete the watch */
333cb5fe245SEnji Cooper     kev.flags = EV_DELETE;
334cb5fe245SEnji Cooper     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
335cb5fe245SEnji Cooper         err(1, "%s", test_id);
336cb5fe245SEnji Cooper 
337cb5fe245SEnji Cooper     success();
338cb5fe245SEnji Cooper }
339cb5fe245SEnji Cooper 
340cb5fe245SEnji Cooper void
test_kevent_signal_del(void)341cb5fe245SEnji Cooper test_kevent_signal_del(void)
342cb5fe245SEnji Cooper {
343cb5fe245SEnji Cooper     const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)";
344cb5fe245SEnji Cooper     struct kevent kev;
345cb5fe245SEnji Cooper 
346cb5fe245SEnji Cooper     test_begin(test_id);
347cb5fe245SEnji Cooper 
348cb5fe245SEnji Cooper     /* Delete the kevent */
349cb5fe245SEnji Cooper     EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL);
350cb5fe245SEnji Cooper     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
351cb5fe245SEnji Cooper         err(1, "%s", test_id);
352cb5fe245SEnji Cooper 
353cb5fe245SEnji Cooper     /* Block SIGUSR1, then send it to ourselves */
354cb5fe245SEnji Cooper     sigset_t mask;
355cb5fe245SEnji Cooper     sigemptyset(&mask);
356cb5fe245SEnji Cooper     sigaddset(&mask, SIGUSR1);
357cb5fe245SEnji Cooper     if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
358cb5fe245SEnji Cooper         err(1, "sigprocmask");
359cb5fe245SEnji Cooper     if (kill(getpid(), SIGUSR1) < 0)
360cb5fe245SEnji Cooper         err(1, "kill");
361cb5fe245SEnji Cooper 
362cb5fe245SEnji Cooper     test_no_kevents();
363cb5fe245SEnji Cooper     success();
364cb5fe245SEnji Cooper }
365cb5fe245SEnji Cooper 
366cb5fe245SEnji Cooper void
test_kevent_signal_oneshot(void)367cb5fe245SEnji Cooper test_kevent_signal_oneshot(void)
368cb5fe245SEnji Cooper {
369cb5fe245SEnji Cooper     const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)";
370cb5fe245SEnji Cooper     struct kevent kev;
371cb5fe245SEnji Cooper 
372cb5fe245SEnji Cooper     test_begin(test_id);
373cb5fe245SEnji Cooper 
374cb5fe245SEnji Cooper     EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL);
375cb5fe245SEnji Cooper     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
376cb5fe245SEnji Cooper         err(1, "%s", test_id);
377cb5fe245SEnji Cooper 
378cb5fe245SEnji Cooper     /* Block SIGUSR1, then send it to ourselves */
379cb5fe245SEnji Cooper     sigset_t mask;
380cb5fe245SEnji Cooper     sigemptyset(&mask);
381cb5fe245SEnji Cooper     sigaddset(&mask, SIGUSR1);
382cb5fe245SEnji Cooper     if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
383cb5fe245SEnji Cooper         err(1, "sigprocmask");
384cb5fe245SEnji Cooper     if (kill(getpid(), SIGUSR1) < 0)
385cb5fe245SEnji Cooper         err(1, "kill");
386cb5fe245SEnji Cooper 
387cb5fe245SEnji Cooper     kev.flags |= EV_CLEAR;
388cb5fe245SEnji Cooper     kev.data = 1;
389cb5fe245SEnji Cooper     kevent_cmp(&kev, kevent_get(kqfd));
390cb5fe245SEnji Cooper 
391cb5fe245SEnji Cooper     /* Send another one and make sure we get no events */
392cb5fe245SEnji Cooper     if (kill(getpid(), SIGUSR1) < 0)
393cb5fe245SEnji Cooper         err(1, "kill");
394cb5fe245SEnji Cooper     test_no_kevents();
395cb5fe245SEnji Cooper 
396cb5fe245SEnji Cooper     success();
397cb5fe245SEnji Cooper }
398cb5fe245SEnji Cooper #endif
399cb5fe245SEnji Cooper 
400cb5fe245SEnji Cooper void
test_evfilt_proc()401cb5fe245SEnji Cooper test_evfilt_proc()
402cb5fe245SEnji Cooper {
403cb5fe245SEnji Cooper     kqfd = kqueue();
404cb5fe245SEnji Cooper 
405cb5fe245SEnji Cooper     signal(SIGUSR1, sig_handler);
406cb5fe245SEnji Cooper 
407cb5fe245SEnji Cooper     add_and_delete();
408cb5fe245SEnji Cooper     proc_track(0); /* Run without sleeping before children exit. */
409cb5fe245SEnji Cooper     proc_track(1); /* Sleep a bit in the children before exiting. */
410cb5fe245SEnji Cooper 
411cb5fe245SEnji Cooper #if TODO
412cb5fe245SEnji Cooper     event_trigger();
413cb5fe245SEnji Cooper #endif
414cb5fe245SEnji Cooper 
415cb5fe245SEnji Cooper     signal(SIGUSR1, SIG_DFL);
416cb5fe245SEnji Cooper 
417cb5fe245SEnji Cooper #if TODO
418cb5fe245SEnji Cooper     test_kevent_signal_add();
419cb5fe245SEnji Cooper     test_kevent_signal_del();
420cb5fe245SEnji Cooper     test_kevent_signal_get();
421cb5fe245SEnji Cooper     test_kevent_signal_disable();
422cb5fe245SEnji Cooper     test_kevent_signal_enable();
423cb5fe245SEnji Cooper     test_kevent_signal_oneshot();
424cb5fe245SEnji Cooper #endif
425cb5fe245SEnji Cooper     close(kqfd);
426cb5fe245SEnji Cooper }
427