xref: /freebsd/tests/sys/kqueue/libkqueue/signal.c (revision a4e5e0106ac7145f56eb39a691e302cabb4635be)
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
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
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
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
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
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
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
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