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