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