xref: /NextBSD/tests/sys/kqueue/proc.c (revision e1dd16d965b177f109afb771e59432e36f335d0a)
1 /*
2  * Copyright (c) 2009 Mark Heily <mark@heily.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  *
16  * $FreeBSD$
17  */
18 
19 #include <sys/stat.h>
20 
21 #include <err.h>
22 
23 #include "config.h"
24 #include "common.h"
25 
26 static int sigusr1_caught = 0;
27 
28 int kqfd;
29 
30 static void
sig_handler(int signum)31 sig_handler(int signum)
32 {
33     sigusr1_caught = 1;
34 }
35 
36 static void
add_and_delete(void)37 add_and_delete(void)
38 {
39     struct kevent kev;
40     pid_t pid;
41 
42     /* Create a child that waits to be killed and then exits */
43     pid = fork();
44     if (pid == 0) {
45         struct stat s;
46         if (fstat(kqfd, &s) != -1)
47             errx(1, "kqueue inherited across fork! (%s() at %s:%d)",
48 	        __func__, __FILE__, __LINE__);
49 
50         pause();
51         exit(2);
52     }
53     printf(" -- child created (pid %d)\n", (int) pid);
54 
55     test_begin("kevent(EVFILT_PROC, EV_ADD)");
56 
57     test_no_kevents();
58     kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD, 0, 0, NULL);
59     test_no_kevents();
60 
61     success();
62 
63     test_begin("kevent(EVFILT_PROC, EV_DELETE)");
64 
65     sleep(1);
66     test_no_kevents();
67     kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_DELETE, 0, 0, NULL);
68     if (kill(pid, SIGKILL) < 0)
69         err(1, "kill");
70     sleep(1);
71     test_no_kevents();
72 
73     success();
74 
75 }
76 
77 #ifdef TODO
78 static void
event_trigger(void)79 event_trigger(void)
80 {
81     struct kevent kev;
82     pid_t pid;
83 
84     test_begin("kevent(EVFILT_PROC, wait)");
85 
86     /* Create a child that waits to be killed and then exits */
87     pid = fork();
88     if (pid == 0) {
89         pause();
90         printf(" -- child caught signal, exiting\n");
91         exit(2);
92     }
93     printf(" -- child created (pid %d)\n", (int) pid);
94 
95     test_no_kevents();
96     kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD, 0, 0, NULL);
97 
98     /* Cause the child to exit, then retrieve the event */
99     printf(" -- killing process %d\n", (int) pid);
100     if (kill(pid, SIGUSR1) < 0)
101         err(1, "kill");
102     kevent_cmp(&kev, kevent_get(kqfd));
103     test_no_kevents();
104 
105     success();
106 }
107 
108 void
test_kevent_signal_disable(void)109 test_kevent_signal_disable(void)
110 {
111     const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)";
112     struct kevent kev;
113 
114     test_begin(test_id);
115 
116     EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL);
117     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
118         err(1, "%s", test_id);
119 
120     /* Block SIGUSR1, then send it to ourselves */
121     sigset_t mask;
122     sigemptyset(&mask);
123     sigaddset(&mask, SIGUSR1);
124     if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
125         err(1, "sigprocmask");
126     if (kill(getpid(), SIGKILL) < 0)
127         err(1, "kill");
128 
129     test_no_kevents();
130 
131     success();
132 }
133 
134 void
test_kevent_signal_enable(void)135 test_kevent_signal_enable(void)
136 {
137     const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)";
138     struct kevent kev;
139 
140     test_begin(test_id);
141 
142     EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL);
143     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
144         err(1, "%s", test_id);
145 
146     /* Block SIGUSR1, then send it to ourselves */
147     sigset_t mask;
148     sigemptyset(&mask);
149     sigaddset(&mask, SIGUSR1);
150     if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
151         err(1, "sigprocmask");
152     if (kill(getpid(), SIGUSR1) < 0)
153         err(1, "kill");
154 
155     kev.flags = EV_ADD | EV_CLEAR;
156 #if LIBKQUEUE
157     kev.data = 1; /* WORKAROUND */
158 #else
159     kev.data = 2; // one extra time from test_kevent_signal_disable()
160 #endif
161     kevent_cmp(&kev, kevent_get(kqfd));
162 
163     /* Delete the watch */
164     kev.flags = EV_DELETE;
165     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
166         err(1, "%s", test_id);
167 
168     success();
169 }
170 
171 void
test_kevent_signal_del(void)172 test_kevent_signal_del(void)
173 {
174     const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)";
175     struct kevent kev;
176 
177     test_begin(test_id);
178 
179     /* Delete the kevent */
180     EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL);
181     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
182         err(1, "%s", test_id);
183 
184     /* Block SIGUSR1, then send it to ourselves */
185     sigset_t mask;
186     sigemptyset(&mask);
187     sigaddset(&mask, SIGUSR1);
188     if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
189         err(1, "sigprocmask");
190     if (kill(getpid(), SIGUSR1) < 0)
191         err(1, "kill");
192 
193     test_no_kevents();
194     success();
195 }
196 
197 void
test_kevent_signal_oneshot(void)198 test_kevent_signal_oneshot(void)
199 {
200     const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)";
201     struct kevent kev;
202 
203     test_begin(test_id);
204 
205     EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL);
206     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
207         err(1, "%s", test_id);
208 
209     /* Block SIGUSR1, then send it to ourselves */
210     sigset_t mask;
211     sigemptyset(&mask);
212     sigaddset(&mask, SIGUSR1);
213     if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
214         err(1, "sigprocmask");
215     if (kill(getpid(), SIGUSR1) < 0)
216         err(1, "kill");
217 
218     kev.flags |= EV_CLEAR;
219     kev.data = 1;
220     kevent_cmp(&kev, kevent_get(kqfd));
221 
222     /* Send another one and make sure we get no events */
223     if (kill(getpid(), SIGUSR1) < 0)
224         err(1, "kill");
225     test_no_kevents();
226 
227     success();
228 }
229 #endif
230 
231 void
test_evfilt_proc()232 test_evfilt_proc()
233 {
234     kqfd = kqueue();
235 
236     signal(SIGUSR1, sig_handler);
237 
238     add_and_delete();
239 
240 #if TODO
241     event_trigger();
242 #endif
243 
244     signal(SIGUSR1, SIG_DFL);
245 
246 #if TODO
247     test_kevent_signal_add();
248     test_kevent_signal_del();
249     test_kevent_signal_get();
250     test_kevent_signal_disable();
251     test_kevent_signal_enable();
252     test_kevent_signal_oneshot();
253 #endif
254     close(kqfd);
255 }
256