1 | /* Copyright Joyent, Inc. and other Node contributors. All rights reserved. |
2 | * |
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
4 | * of this software and associated documentation files (the "Software"), to |
5 | * deal in the Software without restriction, including without limitation the |
6 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
7 | * sell copies of the Software, and to permit persons to whom the Software is |
8 | * furnished to do so, subject to the following conditions: |
9 | * |
10 | * The above copyright notice and this permission notice shall be included in |
11 | * all copies or substantial portions of the Software. |
12 | * |
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
19 | * IN THE SOFTWARE. |
20 | */ |
21 | |
22 | #include "uv.h" |
23 | #include "task.h" |
24 | |
25 | #ifndef _WIN32 |
26 | #include <unistd.h> |
27 | #endif |
28 | |
29 | TEST_IMPL(kill_invalid_signum) { |
30 | uv_pid_t pid; |
31 | |
32 | pid = uv_os_getpid(); |
33 | |
34 | ASSERT(uv_kill(pid, -1) == UV_EINVAL); |
35 | #ifdef _WIN32 |
36 | /* NSIG is not available on all platforms. */ |
37 | ASSERT(uv_kill(pid, NSIG) == UV_EINVAL); |
38 | #endif |
39 | ASSERT(uv_kill(pid, 4096) == UV_EINVAL); |
40 | |
41 | MAKE_VALGRIND_HAPPY(); |
42 | return 0; |
43 | } |
44 | |
45 | /* For Windows we test only signum handling */ |
46 | #ifdef _WIN32 |
47 | static void signum_test_cb(uv_signal_t* handle, int signum) { |
48 | FATAL("signum_test_cb should not be called" ); |
49 | } |
50 | |
51 | TEST_IMPL(win32_signum_number) { |
52 | uv_signal_t signal; |
53 | uv_loop_t* loop; |
54 | |
55 | loop = uv_default_loop(); |
56 | uv_signal_init(loop, &signal); |
57 | |
58 | ASSERT(uv_signal_start(&signal, signum_test_cb, 0) == UV_EINVAL); |
59 | ASSERT(uv_signal_start(&signal, signum_test_cb, SIGINT) == 0); |
60 | ASSERT(uv_signal_start(&signal, signum_test_cb, SIGBREAK) == 0); |
61 | ASSERT(uv_signal_start(&signal, signum_test_cb, SIGHUP) == 0); |
62 | ASSERT(uv_signal_start(&signal, signum_test_cb, SIGWINCH) == 0); |
63 | ASSERT(uv_signal_start(&signal, signum_test_cb, SIGILL) == 0); |
64 | ASSERT(uv_signal_start(&signal, signum_test_cb, SIGABRT_COMPAT) == 0); |
65 | ASSERT(uv_signal_start(&signal, signum_test_cb, SIGFPE) == 0); |
66 | ASSERT(uv_signal_start(&signal, signum_test_cb, SIGSEGV) == 0); |
67 | ASSERT(uv_signal_start(&signal, signum_test_cb, SIGTERM) == 0); |
68 | ASSERT(uv_signal_start(&signal, signum_test_cb, SIGABRT) == 0); |
69 | ASSERT(uv_signal_start(&signal, signum_test_cb, -1) == UV_EINVAL); |
70 | ASSERT(uv_signal_start(&signal, signum_test_cb, NSIG) == UV_EINVAL); |
71 | ASSERT(uv_signal_start(&signal, signum_test_cb, 1024) == UV_EINVAL); |
72 | MAKE_VALGRIND_HAPPY(); |
73 | return 0; |
74 | } |
75 | #else |
76 | #include <errno.h> |
77 | #include <signal.h> |
78 | #include <stdarg.h> |
79 | #include <stdio.h> |
80 | #include <stdlib.h> |
81 | #include <string.h> |
82 | #include <unistd.h> |
83 | |
84 | #define NSIGNALS 10 |
85 | |
86 | struct timer_ctx { |
87 | unsigned int ncalls; |
88 | uv_timer_t handle; |
89 | int signum; |
90 | }; |
91 | |
92 | struct signal_ctx { |
93 | enum { CLOSE, STOP, NOOP } stop_or_close; |
94 | unsigned int ncalls; |
95 | uv_signal_t handle; |
96 | int signum; |
97 | int one_shot; |
98 | }; |
99 | |
100 | |
101 | static void signal_cb(uv_signal_t* handle, int signum) { |
102 | struct signal_ctx* ctx = container_of(handle, struct signal_ctx, handle); |
103 | ASSERT(signum == ctx->signum); |
104 | if (++ctx->ncalls == NSIGNALS) { |
105 | if (ctx->stop_or_close == STOP) |
106 | uv_signal_stop(handle); |
107 | else if (ctx->stop_or_close == CLOSE) |
108 | uv_close((uv_handle_t*)handle, NULL); |
109 | else |
110 | ASSERT(0); |
111 | } |
112 | } |
113 | |
114 | static void signal_cb_one_shot(uv_signal_t* handle, int signum) { |
115 | struct signal_ctx* ctx = container_of(handle, struct signal_ctx, handle); |
116 | ASSERT(signum == ctx->signum); |
117 | ASSERT(++ctx->ncalls == 1); |
118 | if (ctx->stop_or_close == CLOSE) |
119 | uv_close((uv_handle_t*)handle, NULL); |
120 | } |
121 | |
122 | |
123 | static void timer_cb(uv_timer_t* handle) { |
124 | struct timer_ctx* ctx = container_of(handle, struct timer_ctx, handle); |
125 | |
126 | raise(ctx->signum); |
127 | |
128 | if (++ctx->ncalls == NSIGNALS) |
129 | uv_close((uv_handle_t*)handle, NULL); |
130 | } |
131 | |
132 | |
133 | static void start_watcher(uv_loop_t* loop, |
134 | int signum, |
135 | struct signal_ctx* ctx, |
136 | int one_shot) { |
137 | ctx->ncalls = 0; |
138 | ctx->signum = signum; |
139 | ctx->stop_or_close = CLOSE; |
140 | ctx->one_shot = one_shot; |
141 | ASSERT(0 == uv_signal_init(loop, &ctx->handle)); |
142 | if (one_shot) |
143 | ASSERT(0 == uv_signal_start_oneshot(&ctx->handle, signal_cb_one_shot, signum)); |
144 | else |
145 | ASSERT(0 == uv_signal_start(&ctx->handle, signal_cb, signum)); |
146 | } |
147 | |
148 | static void start_timer(uv_loop_t* loop, int signum, struct timer_ctx* ctx) { |
149 | ctx->ncalls = 0; |
150 | ctx->signum = signum; |
151 | ASSERT(0 == uv_timer_init(loop, &ctx->handle)); |
152 | ASSERT(0 == uv_timer_start(&ctx->handle, timer_cb, 5, 5)); |
153 | } |
154 | |
155 | |
156 | TEST_IMPL(we_get_signal) { |
157 | struct signal_ctx sc; |
158 | struct timer_ctx tc; |
159 | uv_loop_t* loop; |
160 | |
161 | loop = uv_default_loop(); |
162 | start_timer(loop, SIGCHLD, &tc); |
163 | start_watcher(loop, SIGCHLD, &sc, 0); |
164 | sc.stop_or_close = STOP; /* stop, don't close the signal handle */ |
165 | ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); |
166 | ASSERT(tc.ncalls == NSIGNALS); |
167 | ASSERT(sc.ncalls == NSIGNALS); |
168 | |
169 | start_timer(loop, SIGCHLD, &tc); |
170 | ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); |
171 | ASSERT(tc.ncalls == NSIGNALS); |
172 | ASSERT(sc.ncalls == NSIGNALS); |
173 | |
174 | sc.ncalls = 0; |
175 | sc.stop_or_close = CLOSE; /* now close it when it's done */ |
176 | uv_signal_start(&sc.handle, signal_cb, SIGCHLD); |
177 | |
178 | start_timer(loop, SIGCHLD, &tc); |
179 | ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); |
180 | ASSERT(tc.ncalls == NSIGNALS); |
181 | ASSERT(sc.ncalls == NSIGNALS); |
182 | |
183 | MAKE_VALGRIND_HAPPY(); |
184 | return 0; |
185 | } |
186 | |
187 | |
188 | TEST_IMPL(we_get_signals) { |
189 | struct signal_ctx sc[4]; |
190 | struct timer_ctx tc[2]; |
191 | uv_loop_t* loop; |
192 | unsigned int i; |
193 | |
194 | loop = uv_default_loop(); |
195 | start_watcher(loop, SIGUSR1, sc + 0, 0); |
196 | start_watcher(loop, SIGUSR1, sc + 1, 0); |
197 | start_watcher(loop, SIGUSR2, sc + 2, 0); |
198 | start_watcher(loop, SIGUSR2, sc + 3, 0); |
199 | start_timer(loop, SIGUSR1, tc + 0); |
200 | start_timer(loop, SIGUSR2, tc + 1); |
201 | ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); |
202 | |
203 | for (i = 0; i < ARRAY_SIZE(sc); i++) |
204 | ASSERT(sc[i].ncalls == NSIGNALS); |
205 | |
206 | for (i = 0; i < ARRAY_SIZE(tc); i++) |
207 | ASSERT(tc[i].ncalls == NSIGNALS); |
208 | |
209 | MAKE_VALGRIND_HAPPY(); |
210 | return 0; |
211 | } |
212 | |
213 | TEST_IMPL(we_get_signal_one_shot) { |
214 | struct signal_ctx sc; |
215 | struct timer_ctx tc; |
216 | uv_loop_t* loop; |
217 | |
218 | loop = uv_default_loop(); |
219 | start_timer(loop, SIGCHLD, &tc); |
220 | start_watcher(loop, SIGCHLD, &sc, 1); |
221 | sc.stop_or_close = NOOP; |
222 | ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); |
223 | ASSERT(tc.ncalls == NSIGNALS); |
224 | ASSERT(sc.ncalls == 1); |
225 | |
226 | start_timer(loop, SIGCHLD, &tc); |
227 | ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); |
228 | ASSERT(sc.ncalls == 1); |
229 | |
230 | sc.ncalls = 0; |
231 | sc.stop_or_close = CLOSE; /* now close it when it's done */ |
232 | uv_signal_start_oneshot(&sc.handle, signal_cb_one_shot, SIGCHLD); |
233 | start_timer(loop, SIGCHLD, &tc); |
234 | ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); |
235 | ASSERT(tc.ncalls == NSIGNALS); |
236 | ASSERT(sc.ncalls == 1); |
237 | |
238 | MAKE_VALGRIND_HAPPY(); |
239 | return 0; |
240 | } |
241 | |
242 | TEST_IMPL(we_get_signals_mixed) { |
243 | struct signal_ctx sc[4]; |
244 | struct timer_ctx tc; |
245 | uv_loop_t* loop; |
246 | |
247 | loop = uv_default_loop(); |
248 | |
249 | /* 2 one-shot */ |
250 | start_timer(loop, SIGCHLD, &tc); |
251 | start_watcher(loop, SIGCHLD, sc + 0, 1); |
252 | start_watcher(loop, SIGCHLD, sc + 1, 1); |
253 | sc[0].stop_or_close = CLOSE; |
254 | sc[1].stop_or_close = CLOSE; |
255 | ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); |
256 | ASSERT(tc.ncalls == NSIGNALS); |
257 | ASSERT(sc[0].ncalls == 1); |
258 | ASSERT(sc[1].ncalls == 1); |
259 | |
260 | /* 2 one-shot, 1 normal then remove normal */ |
261 | start_timer(loop, SIGCHLD, &tc); |
262 | start_watcher(loop, SIGCHLD, sc + 0, 1); |
263 | start_watcher(loop, SIGCHLD, sc + 1, 1); |
264 | sc[0].stop_or_close = CLOSE; |
265 | sc[1].stop_or_close = CLOSE; |
266 | start_watcher(loop, SIGCHLD, sc + 2, 0); |
267 | uv_close((uv_handle_t*)&(sc[2]).handle, NULL); |
268 | ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); |
269 | ASSERT(tc.ncalls == NSIGNALS); |
270 | ASSERT(sc[0].ncalls == 1); |
271 | ASSERT(sc[1].ncalls == 1); |
272 | ASSERT(sc[2].ncalls == 0); |
273 | |
274 | /* 2 normal, 1 one-shot then remove one-shot */ |
275 | start_timer(loop, SIGCHLD, &tc); |
276 | start_watcher(loop, SIGCHLD, sc + 0, 0); |
277 | start_watcher(loop, SIGCHLD, sc + 1, 0); |
278 | sc[0].stop_or_close = CLOSE; |
279 | sc[1].stop_or_close = CLOSE; |
280 | start_watcher(loop, SIGCHLD, sc + 2, 1); |
281 | uv_close((uv_handle_t*)&(sc[2]).handle, NULL); |
282 | ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); |
283 | ASSERT(tc.ncalls == NSIGNALS); |
284 | ASSERT(sc[0].ncalls == NSIGNALS); |
285 | ASSERT(sc[1].ncalls == NSIGNALS); |
286 | ASSERT(sc[2].ncalls == 0); |
287 | |
288 | /* 2 normal, 2 one-shot then remove 2 normal */ |
289 | start_timer(loop, SIGCHLD, &tc); |
290 | start_watcher(loop, SIGCHLD, sc + 0, 0); |
291 | start_watcher(loop, SIGCHLD, sc + 1, 0); |
292 | start_watcher(loop, SIGCHLD, sc + 2, 1); |
293 | start_watcher(loop, SIGCHLD, sc + 3, 1); |
294 | sc[2].stop_or_close = CLOSE; |
295 | sc[3].stop_or_close = CLOSE; |
296 | uv_close((uv_handle_t*)&(sc[0]).handle, NULL); |
297 | uv_close((uv_handle_t*)&(sc[1]).handle, NULL); |
298 | ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); |
299 | ASSERT(tc.ncalls == NSIGNALS); |
300 | ASSERT(sc[0].ncalls == 0); |
301 | ASSERT(sc[1].ncalls == 0); |
302 | ASSERT(sc[2].ncalls == 1); |
303 | ASSERT(sc[2].ncalls == 1); |
304 | |
305 | /* 1 normal, 1 one-shot, 2 normal then remove 1st normal, 2nd normal */ |
306 | start_timer(loop, SIGCHLD, &tc); |
307 | start_watcher(loop, SIGCHLD, sc + 0, 0); |
308 | start_watcher(loop, SIGCHLD, sc + 1, 1); |
309 | start_watcher(loop, SIGCHLD, sc + 2, 0); |
310 | start_watcher(loop, SIGCHLD, sc + 3, 0); |
311 | sc[3].stop_or_close = CLOSE; |
312 | uv_close((uv_handle_t*)&(sc[0]).handle, NULL); |
313 | uv_close((uv_handle_t*)&(sc[2]).handle, NULL); |
314 | ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); |
315 | ASSERT(tc.ncalls == NSIGNALS); |
316 | ASSERT(sc[0].ncalls == 0); |
317 | ASSERT(sc[1].ncalls == 1); |
318 | ASSERT(sc[2].ncalls == 0); |
319 | ASSERT(sc[3].ncalls == NSIGNALS); |
320 | |
321 | MAKE_VALGRIND_HAPPY(); |
322 | return 0; |
323 | } |
324 | |
325 | #endif /* _WIN32 */ |
326 | |