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