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