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