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
17 #include "common.h"
18
19
20 static void
test_kevent_signal_add(void)21 test_kevent_signal_add(void)
22 {
23 const char *test_id = "kevent(EVFILT_SIGNAL, EV_ADD)";
24 struct kevent kev;
25
26 test_begin(test_id);
27
28 EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
29 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
30 err(1, "%s", test_id);
31
32 success();
33 }
34
35 static void
test_kevent_signal_get(void)36 test_kevent_signal_get(void)
37 {
38 const char *test_id = "kevent(EVFILT_SIGNAL, wait)";
39 struct kevent kev;
40
41 test_begin(test_id);
42
43 EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
44 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
45 err(1, "%s", test_id);
46
47 /* Block SIGUSR1, then send it to ourselves */
48 sigset_t mask;
49 sigemptyset(&mask);
50 sigaddset(&mask, SIGUSR1);
51 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
52 err(1, "sigprocmask");
53 if (kill(getpid(), SIGUSR1) < 0)
54 err(1, "kill");
55
56 kev.flags |= EV_CLEAR;
57 kev.data = 1;
58 kevent_cmp(&kev, kevent_get(kqfd));
59
60 success();
61 }
62
63 static void
test_kevent_signal_disable(void)64 test_kevent_signal_disable(void)
65 {
66 const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)";
67 struct kevent kev;
68
69 test_begin(test_id);
70
71 EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL);
72 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
73 err(1, "%s", test_id);
74
75 /* Block SIGUSR1, then send it to ourselves */
76 sigset_t mask;
77 sigemptyset(&mask);
78 sigaddset(&mask, SIGUSR1);
79 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
80 err(1, "sigprocmask");
81 if (kill(getpid(), SIGUSR1) < 0)
82 err(1, "kill");
83
84 test_no_kevents();
85
86 success();
87 }
88
89 static void
test_kevent_signal_enable(void)90 test_kevent_signal_enable(void)
91 {
92 const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)";
93 struct kevent kev;
94
95 test_begin(test_id);
96
97 EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL);
98 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
99 err(1, "%s", test_id);
100
101 /* Block SIGUSR1, then send it to ourselves */
102 sigset_t mask;
103 sigemptyset(&mask);
104 sigaddset(&mask, SIGUSR1);
105 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
106 err(1, "sigprocmask");
107 if (kill(getpid(), SIGUSR1) < 0)
108 err(1, "kill");
109
110 kev.flags = EV_ADD | EV_CLEAR;
111 #if LIBKQUEUE
112 kev.data = 1; /* WORKAROUND */
113 #else
114 kev.data = 2; // one extra time from test_kevent_signal_disable()
115 #endif
116 kevent_cmp(&kev, kevent_get(kqfd));
117
118 /* Delete the watch */
119 kev.flags = EV_DELETE;
120 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
121 err(1, "%s", test_id);
122
123 success();
124 }
125
126 static void
test_kevent_signal_del(void)127 test_kevent_signal_del(void)
128 {
129 const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)";
130 struct kevent kev;
131
132 test_begin(test_id);
133
134 /* Delete the kevent */
135 EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL);
136 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
137 err(1, "%s", test_id);
138
139 /* Block SIGUSR1, then send it to ourselves */
140 sigset_t mask;
141 sigemptyset(&mask);
142 sigaddset(&mask, SIGUSR1);
143 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
144 err(1, "sigprocmask");
145 if (kill(getpid(), SIGUSR1) < 0)
146 err(1, "kill");
147
148 test_no_kevents();
149 success();
150 }
151
152 static void
test_kevent_signal_oneshot(void)153 test_kevent_signal_oneshot(void)
154 {
155 const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)";
156 struct kevent kev;
157
158 test_begin(test_id);
159
160 EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL);
161 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
162 err(1, "%s", test_id);
163
164 /* Block SIGUSR1, then send it to ourselves */
165 sigset_t mask;
166 sigemptyset(&mask);
167 sigaddset(&mask, SIGUSR1);
168 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
169 err(1, "sigprocmask");
170 if (kill(getpid(), SIGUSR1) < 0)
171 err(1, "kill");
172
173 kev.flags |= EV_CLEAR;
174 kev.data = 1;
175 kevent_cmp(&kev, kevent_get(kqfd));
176
177 /* Send another one and make sure we get no events */
178 if (kill(getpid(), SIGUSR1) < 0)
179 err(1, "kill");
180 test_no_kevents();
181
182 success();
183 }
184
185 void
test_evfilt_signal(void)186 test_evfilt_signal(void)
187 {
188 kqfd = kqueue();
189 test_kevent_signal_add();
190 test_kevent_signal_del();
191 test_kevent_signal_get();
192 test_kevent_signal_disable();
193 test_kevent_signal_enable();
194 test_kevent_signal_oneshot();
195 close(kqfd);
196 }
197