/src/CMake/Utilities/cmlibuv/src/unix/signal.c
Line | Count | Source |
1 | | /* Copyright Joyent, Inc. and other Node contributors. All rights reserved. |
2 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
3 | | * of this software and associated documentation files (the "Software"), to |
4 | | * deal in the Software without restriction, including without limitation the |
5 | | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
6 | | * sell copies of the Software, and to permit persons to whom the Software is |
7 | | * furnished to do so, subject to the following conditions: |
8 | | * |
9 | | * The above copyright notice and this permission notice shall be included in |
10 | | * all copies or substantial portions of the Software. |
11 | | * |
12 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
13 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
14 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
15 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
16 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
17 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
18 | | * IN THE SOFTWARE. |
19 | | */ |
20 | | |
21 | | #include "uv.h" |
22 | | #include "internal.h" |
23 | | |
24 | | #include <assert.h> |
25 | | #include <errno.h> |
26 | | #include <signal.h> |
27 | | #include <stdlib.h> |
28 | | #include <string.h> |
29 | | #include <unistd.h> |
30 | | |
31 | | #ifndef SA_RESTART |
32 | | # define SA_RESTART 0 |
33 | | #endif |
34 | | |
35 | | typedef struct { |
36 | | uv_signal_t* handle; |
37 | | int signum; |
38 | | } uv__signal_msg_t; |
39 | | |
40 | | RB_HEAD(uv__signal_tree_s, uv_signal_s); |
41 | | |
42 | | |
43 | | static int uv__signal_unlock(void); |
44 | | static int uv__signal_start(uv_signal_t* handle, |
45 | | uv_signal_cb signal_cb, |
46 | | int signum, |
47 | | int oneshot); |
48 | | static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2); |
49 | | static void uv__signal_stop(uv_signal_t* handle); |
50 | | static void uv__signal_unregister_handler(int signum); |
51 | | |
52 | | |
53 | | static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT; |
54 | | static struct uv__signal_tree_s uv__signal_tree = |
55 | | RB_INITIALIZER(uv__signal_tree); |
56 | | static int uv__signal_lock_pipefd[2] = { -1, -1 }; |
57 | | |
58 | 0 | RB_GENERATE_STATIC(uv__signal_tree_s, Unexecuted instantiation: signal.c:uv__signal_tree_s_RB_NFIND Unexecuted instantiation: signal.c:uv__signal_tree_s_RB_INSERT Unexecuted instantiation: signal.c:uv__signal_tree_s_RB_INSERT_COLOR Unexecuted instantiation: signal.c:uv__signal_tree_s_RB_REMOVE Unexecuted instantiation: signal.c:uv__signal_tree_s_RB_REMOVE_COLOR |
59 | 0 | uv_signal_s, tree_entry, |
60 | 0 | uv__signal_compare) |
61 | 0 |
|
62 | 0 | static void uv__signal_global_reinit(void); |
63 | 0 |
|
64 | 0 | static void uv__signal_global_init(void) { |
65 | 0 | if (uv__signal_lock_pipefd[0] == -1) |
66 | | /* pthread_atfork can register before and after handlers, one |
67 | | * for each child. This only registers one for the child. That |
68 | | * state is both persistent and cumulative, so if we keep doing |
69 | | * it the handler functions will be called multiple times. Thus |
70 | | * we only want to do it once. |
71 | | */ |
72 | 0 | if (pthread_atfork(NULL, NULL, &uv__signal_global_reinit)) |
73 | 0 | abort(); |
74 | | |
75 | 0 | uv__signal_global_reinit(); |
76 | 0 | } |
77 | | |
78 | | |
79 | 0 | void uv__signal_cleanup(void) { |
80 | | /* We can only use signal-safe functions here. |
81 | | * That includes read/write and close, fortunately. |
82 | | * We do all of this directly here instead of resetting |
83 | | * uv__signal_global_init_guard because |
84 | | * uv__signal_global_once_init is only called from uv_loop_init |
85 | | * and this needs to function in existing loops. |
86 | | */ |
87 | 0 | if (uv__signal_lock_pipefd[0] != -1) { |
88 | 0 | uv__close(uv__signal_lock_pipefd[0]); |
89 | 0 | uv__signal_lock_pipefd[0] = -1; |
90 | 0 | } |
91 | |
|
92 | 0 | if (uv__signal_lock_pipefd[1] != -1) { |
93 | 0 | uv__close(uv__signal_lock_pipefd[1]); |
94 | 0 | uv__signal_lock_pipefd[1] = -1; |
95 | 0 | } |
96 | 0 | } |
97 | | |
98 | | |
99 | 0 | static void uv__signal_global_reinit(void) { |
100 | 0 | uv__signal_cleanup(); |
101 | |
|
102 | 0 | if (uv__make_pipe(uv__signal_lock_pipefd, 0)) |
103 | 0 | abort(); |
104 | | |
105 | 0 | if (uv__signal_unlock()) |
106 | 0 | abort(); |
107 | 0 | } |
108 | | |
109 | | |
110 | 0 | void uv__signal_global_once_init(void) { |
111 | 0 | uv_once(&uv__signal_global_init_guard, uv__signal_global_init); |
112 | 0 | } |
113 | | |
114 | | |
115 | 0 | static int uv__signal_lock(void) { |
116 | 0 | int r; |
117 | 0 | char data; |
118 | |
|
119 | 0 | do { |
120 | 0 | r = read(uv__signal_lock_pipefd[0], &data, sizeof data); |
121 | 0 | } while (r < 0 && errno == EINTR); |
122 | |
|
123 | 0 | return (r < 0) ? -1 : 0; |
124 | 0 | } |
125 | | |
126 | | |
127 | 0 | static int uv__signal_unlock(void) { |
128 | 0 | int r; |
129 | 0 | char data = 42; |
130 | |
|
131 | 0 | do { |
132 | 0 | r = write(uv__signal_lock_pipefd[1], &data, sizeof data); |
133 | 0 | } while (r < 0 && errno == EINTR); |
134 | |
|
135 | 0 | return (r < 0) ? -1 : 0; |
136 | 0 | } |
137 | | |
138 | | |
139 | 0 | static void uv__signal_block_and_lock(sigset_t* saved_sigmask) { |
140 | 0 | sigset_t new_mask; |
141 | |
|
142 | 0 | if (sigfillset(&new_mask)) |
143 | 0 | abort(); |
144 | | |
145 | | /* to shut up valgrind */ |
146 | 0 | sigemptyset(saved_sigmask); |
147 | 0 | if (pthread_sigmask(SIG_SETMASK, &new_mask, saved_sigmask)) |
148 | 0 | abort(); |
149 | | |
150 | 0 | if (uv__signal_lock()) |
151 | 0 | abort(); |
152 | 0 | } |
153 | | |
154 | | |
155 | 0 | static void uv__signal_unlock_and_unblock(sigset_t* saved_sigmask) { |
156 | 0 | if (uv__signal_unlock()) |
157 | 0 | abort(); |
158 | | |
159 | 0 | if (pthread_sigmask(SIG_SETMASK, saved_sigmask, NULL)) |
160 | 0 | abort(); |
161 | 0 | } |
162 | | |
163 | | |
164 | 0 | static uv_signal_t* uv__signal_first_handle(int signum) { |
165 | | /* This function must be called with the signal lock held. */ |
166 | 0 | uv_signal_t lookup; |
167 | 0 | uv_signal_t* handle; |
168 | |
|
169 | 0 | lookup.signum = signum; |
170 | 0 | lookup.flags = 0; |
171 | 0 | lookup.loop = NULL; |
172 | |
|
173 | 0 | handle = RB_NFIND(uv__signal_tree_s, &uv__signal_tree, &lookup); |
174 | |
|
175 | 0 | if (handle != NULL && handle->signum == signum) |
176 | 0 | return handle; |
177 | | |
178 | 0 | return NULL; |
179 | 0 | } |
180 | | |
181 | | |
182 | 0 | static void uv__signal_handler(int signum) { |
183 | 0 | uv__signal_msg_t msg; |
184 | 0 | uv_signal_t* handle; |
185 | 0 | int saved_errno; |
186 | |
|
187 | 0 | saved_errno = errno; |
188 | 0 | memset(&msg, 0, sizeof msg); |
189 | |
|
190 | 0 | if (uv__signal_lock()) { |
191 | 0 | errno = saved_errno; |
192 | 0 | return; |
193 | 0 | } |
194 | | |
195 | 0 | for (handle = uv__signal_first_handle(signum); |
196 | 0 | handle != NULL && handle->signum == signum; |
197 | 0 | handle = RB_NEXT(uv__signal_tree_s, handle)) { |
198 | 0 | int r; |
199 | |
|
200 | 0 | msg.signum = signum; |
201 | 0 | msg.handle = handle; |
202 | | |
203 | | /* write() should be atomic for small data chunks, so the entire message |
204 | | * should be written at once. In theory the pipe could become full, in |
205 | | * which case the user is out of luck. |
206 | | */ |
207 | 0 | do { |
208 | 0 | r = write(handle->loop->signal_pipefd[1], &msg, sizeof msg); |
209 | 0 | } while (r == -1 && errno == EINTR); |
210 | |
|
211 | 0 | assert(r == sizeof msg || |
212 | 0 | (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))); |
213 | |
|
214 | 0 | if (r != -1) |
215 | 0 | handle->caught_signals++; |
216 | 0 | } |
217 | |
|
218 | 0 | uv__signal_unlock(); |
219 | 0 | errno = saved_errno; |
220 | 0 | } |
221 | | |
222 | | |
223 | 0 | static int uv__signal_register_handler(int signum, int oneshot) { |
224 | | /* When this function is called, the signal lock must be held. */ |
225 | 0 | struct sigaction sa; |
226 | | |
227 | | /* XXX use a separate signal stack? */ |
228 | 0 | memset(&sa, 0, sizeof(sa)); |
229 | 0 | if (sigfillset(&sa.sa_mask)) |
230 | 0 | abort(); |
231 | 0 | sa.sa_handler = uv__signal_handler; |
232 | 0 | sa.sa_flags = SA_RESTART; |
233 | 0 | if (oneshot) |
234 | 0 | sa.sa_flags |= SA_RESETHAND; |
235 | | |
236 | | /* XXX save old action so we can restore it later on? */ |
237 | 0 | if (sigaction(signum, &sa, NULL)) |
238 | 0 | return UV__ERR(errno); |
239 | | |
240 | 0 | return 0; |
241 | 0 | } |
242 | | |
243 | | |
244 | 0 | static void uv__signal_unregister_handler(int signum) { |
245 | | /* When this function is called, the signal lock must be held. */ |
246 | 0 | struct sigaction sa; |
247 | |
|
248 | 0 | memset(&sa, 0, sizeof(sa)); |
249 | 0 | sa.sa_handler = SIG_DFL; |
250 | | |
251 | | /* sigaction can only fail with EINVAL or EFAULT; an attempt to deregister a |
252 | | * signal implies that it was successfully registered earlier, so EINVAL |
253 | | * should never happen. |
254 | | */ |
255 | 0 | if (sigaction(signum, &sa, NULL)) |
256 | 0 | abort(); |
257 | 0 | } |
258 | | |
259 | | |
260 | 0 | static int uv__signal_loop_once_init(uv_loop_t* loop) { |
261 | 0 | int* pipefd; |
262 | 0 | int err; |
263 | | |
264 | | /* Return if already initialized. */ |
265 | 0 | pipefd = loop->signal_pipefd; |
266 | 0 | if (pipefd[0] != -1) |
267 | 0 | return 0; |
268 | | |
269 | 0 | err = uv__make_pipe(pipefd, UV_NONBLOCK_PIPE); |
270 | 0 | if (err) |
271 | 0 | return err; |
272 | | |
273 | 0 | err = uv__io_init_start(loop, &loop->signal_io_watcher, UV__SIGNAL_EVENT, |
274 | 0 | pipefd[0], POLLIN); |
275 | 0 | if (err) { |
276 | 0 | uv__close(pipefd[0]); |
277 | 0 | uv__close(pipefd[1]); |
278 | 0 | pipefd[0] = -1; |
279 | 0 | pipefd[1] = -1; |
280 | 0 | } |
281 | |
|
282 | 0 | return err; |
283 | 0 | } |
284 | | |
285 | | |
286 | 0 | int uv__signal_loop_fork(uv_loop_t* loop) { |
287 | 0 | struct uv__queue* q; |
288 | |
|
289 | 0 | if (loop->signal_pipefd[0] == -1) |
290 | 0 | return 0; |
291 | 0 | uv__io_stop(loop, &loop->signal_io_watcher, POLLIN); |
292 | 0 | uv__close(loop->signal_pipefd[0]); |
293 | 0 | uv__close(loop->signal_pipefd[1]); |
294 | 0 | loop->signal_pipefd[0] = -1; |
295 | 0 | loop->signal_pipefd[1] = -1; |
296 | |
|
297 | 0 | uv__queue_foreach(q, &loop->handle_queue) { |
298 | 0 | uv_handle_t* handle = uv__queue_data(q, uv_handle_t, handle_queue); |
299 | 0 | uv_signal_t* sh; |
300 | |
|
301 | 0 | if (handle->type != UV_SIGNAL) |
302 | 0 | continue; |
303 | | |
304 | 0 | sh = (uv_signal_t*) handle; |
305 | 0 | sh->caught_signals = 0; |
306 | 0 | sh->dispatched_signals = 0; |
307 | 0 | } |
308 | |
|
309 | 0 | return uv__signal_loop_once_init(loop); |
310 | 0 | } |
311 | | |
312 | | |
313 | 0 | void uv__signal_loop_cleanup(uv_loop_t* loop) { |
314 | 0 | struct uv__queue* q; |
315 | | |
316 | | /* Stop all the signal watchers that are still attached to this loop. This |
317 | | * ensures that the (shared) signal tree doesn't contain any invalid entries |
318 | | * entries, and that signal handlers are removed when appropriate. |
319 | | * It's safe to use uv__queue_foreach here because the handles and the handle |
320 | | * queue are not modified by uv__signal_stop(). |
321 | | */ |
322 | 0 | uv__queue_foreach(q, &loop->handle_queue) { |
323 | 0 | uv_handle_t* handle = uv__queue_data(q, uv_handle_t, handle_queue); |
324 | |
|
325 | 0 | if (handle->type == UV_SIGNAL) |
326 | 0 | uv__signal_stop((uv_signal_t*) handle); |
327 | 0 | } |
328 | |
|
329 | 0 | if (loop->signal_pipefd[0] != -1) { |
330 | 0 | uv__close(loop->signal_pipefd[0]); |
331 | 0 | loop->signal_pipefd[0] = -1; |
332 | 0 | } |
333 | |
|
334 | 0 | if (loop->signal_pipefd[1] != -1) { |
335 | 0 | uv__close(loop->signal_pipefd[1]); |
336 | 0 | loop->signal_pipefd[1] = -1; |
337 | 0 | } |
338 | 0 | } |
339 | | |
340 | | |
341 | 0 | int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) { |
342 | 0 | int err; |
343 | |
|
344 | 0 | err = uv__signal_loop_once_init(loop); |
345 | 0 | if (err) |
346 | 0 | return err; |
347 | | |
348 | 0 | uv__handle_init(loop, (uv_handle_t*) handle, UV_SIGNAL); |
349 | 0 | handle->signum = 0; |
350 | 0 | handle->caught_signals = 0; |
351 | 0 | handle->dispatched_signals = 0; |
352 | |
|
353 | 0 | return 0; |
354 | 0 | } |
355 | | |
356 | | |
357 | 0 | void uv__signal_close(uv_signal_t* handle) { |
358 | 0 | uv__signal_stop(handle); |
359 | 0 | } |
360 | | |
361 | | |
362 | 0 | int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) { |
363 | 0 | return uv__signal_start(handle, signal_cb, signum, 0); |
364 | 0 | } |
365 | | |
366 | | |
367 | | int uv_signal_start_oneshot(uv_signal_t* handle, |
368 | | uv_signal_cb signal_cb, |
369 | 0 | int signum) { |
370 | 0 | return uv__signal_start(handle, signal_cb, signum, 1); |
371 | 0 | } |
372 | | |
373 | | |
374 | | static int uv__signal_start(uv_signal_t* handle, |
375 | | uv_signal_cb signal_cb, |
376 | | int signum, |
377 | 0 | int oneshot) { |
378 | 0 | sigset_t saved_sigmask; |
379 | 0 | int err; |
380 | 0 | uv_signal_t* first_handle; |
381 | |
|
382 | 0 | assert(!uv__is_closing(handle)); |
383 | | |
384 | | /* If the user supplies signum == 0, then return an error already. If the |
385 | | * signum is otherwise invalid then uv__signal_register will find out |
386 | | * eventually. |
387 | | */ |
388 | 0 | if (signum == 0) |
389 | 0 | return UV_EINVAL; |
390 | | |
391 | | /* Short circuit: if the signal watcher is already watching {signum} don't |
392 | | * go through the process of deregistering and registering the handler. |
393 | | * Additionally, this avoids pending signals getting lost in the small |
394 | | * time frame that handle->signum == 0. |
395 | | */ |
396 | 0 | if (signum == handle->signum) { |
397 | 0 | handle->signal_cb = signal_cb; |
398 | 0 | return 0; |
399 | 0 | } |
400 | | |
401 | | /* If the signal handler was already active, stop it first. */ |
402 | 0 | if (handle->signum != 0) { |
403 | 0 | uv__signal_stop(handle); |
404 | 0 | } |
405 | |
|
406 | 0 | uv__signal_block_and_lock(&saved_sigmask); |
407 | | |
408 | | /* If at this point there are no active signal watchers for this signum (in |
409 | | * any of the loops), it's time to try and register a handler for it here. |
410 | | * Also in case there's only one-shot handlers and a regular handler comes in. |
411 | | */ |
412 | 0 | first_handle = uv__signal_first_handle(signum); |
413 | 0 | if (first_handle == NULL || |
414 | 0 | (!oneshot && (first_handle->flags & UV_SIGNAL_ONE_SHOT))) { |
415 | 0 | err = uv__signal_register_handler(signum, oneshot); |
416 | 0 | if (err) { |
417 | | /* Registering the signal handler failed. Must be an invalid signal. */ |
418 | 0 | uv__signal_unlock_and_unblock(&saved_sigmask); |
419 | 0 | return err; |
420 | 0 | } |
421 | 0 | } |
422 | | |
423 | 0 | handle->signum = signum; |
424 | 0 | if (oneshot) |
425 | 0 | handle->flags |= UV_SIGNAL_ONE_SHOT; |
426 | |
|
427 | 0 | RB_INSERT(uv__signal_tree_s, &uv__signal_tree, handle); |
428 | |
|
429 | 0 | uv__signal_unlock_and_unblock(&saved_sigmask); |
430 | |
|
431 | 0 | handle->signal_cb = signal_cb; |
432 | 0 | uv__handle_start(handle); |
433 | |
|
434 | 0 | return 0; |
435 | 0 | } |
436 | | |
437 | | |
438 | 0 | void uv__signal_event(uv_loop_t* loop, uv__io_t* w, unsigned int events) { |
439 | 0 | uv__signal_msg_t* msg; |
440 | 0 | uv_signal_t* handle; |
441 | 0 | char buf[sizeof(uv__signal_msg_t) * 32]; |
442 | 0 | size_t bytes, end, i; |
443 | 0 | int r; |
444 | |
|
445 | 0 | bytes = 0; |
446 | 0 | end = 0; |
447 | |
|
448 | 0 | do { |
449 | 0 | r = read(loop->signal_pipefd[0], buf + bytes, sizeof(buf) - bytes); |
450 | |
|
451 | 0 | if (r == -1 && errno == EINTR) |
452 | 0 | continue; |
453 | | |
454 | 0 | if (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { |
455 | | /* If there are bytes in the buffer already (which really is extremely |
456 | | * unlikely if possible at all) we can't exit the function here. We'll |
457 | | * spin until more bytes are read instead. |
458 | | */ |
459 | 0 | if (bytes > 0) |
460 | 0 | continue; |
461 | | |
462 | | /* Otherwise, there was nothing there. */ |
463 | 0 | return; |
464 | 0 | } |
465 | | |
466 | | /* Other errors really should never happen. */ |
467 | 0 | if (r == -1) |
468 | 0 | abort(); |
469 | | |
470 | 0 | bytes += r; |
471 | | |
472 | | /* `end` is rounded down to a multiple of sizeof(uv__signal_msg_t). */ |
473 | 0 | end = (bytes / sizeof(uv__signal_msg_t)) * sizeof(uv__signal_msg_t); |
474 | |
|
475 | 0 | for (i = 0; i < end; i += sizeof(uv__signal_msg_t)) { |
476 | 0 | msg = (uv__signal_msg_t*) (buf + i); |
477 | 0 | handle = msg->handle; |
478 | |
|
479 | 0 | if (msg->signum == handle->signum) { |
480 | 0 | assert(!(handle->flags & UV_HANDLE_CLOSING)); |
481 | 0 | handle->signal_cb(handle, handle->signum); |
482 | 0 | } |
483 | |
|
484 | 0 | handle->dispatched_signals++; |
485 | |
|
486 | 0 | if (handle->flags & UV_SIGNAL_ONE_SHOT) |
487 | 0 | uv__signal_stop(handle); |
488 | 0 | } |
489 | |
|
490 | 0 | bytes -= end; |
491 | | |
492 | | /* If there are any "partial" messages left, move them to the start of the |
493 | | * the buffer, and spin. This should not happen. |
494 | | */ |
495 | 0 | if (bytes) { |
496 | 0 | memmove(buf, buf + end, bytes); |
497 | 0 | continue; |
498 | 0 | } |
499 | 0 | } while (end == sizeof buf); |
500 | 0 | } |
501 | | |
502 | | |
503 | 0 | static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) { |
504 | 0 | int f1; |
505 | 0 | int f2; |
506 | | /* Compare signums first so all watchers with the same signnum end up |
507 | | * adjacent. |
508 | | */ |
509 | 0 | if (w1->signum < w2->signum) return -1; |
510 | 0 | if (w1->signum > w2->signum) return 1; |
511 | | |
512 | | /* Handlers without UV_SIGNAL_ONE_SHOT set will come first, so if the first |
513 | | * handler returned is a one-shot handler, the rest will be too. |
514 | | */ |
515 | 0 | f1 = w1->flags & UV_SIGNAL_ONE_SHOT; |
516 | 0 | f2 = w2->flags & UV_SIGNAL_ONE_SHOT; |
517 | 0 | if (f1 < f2) return -1; |
518 | 0 | if (f1 > f2) return 1; |
519 | | |
520 | | /* Sort by loop pointer, so we can easily look up the first item after |
521 | | * { .signum = x, .loop = NULL }. |
522 | | */ |
523 | 0 | if (w1->loop < w2->loop) return -1; |
524 | 0 | if (w1->loop > w2->loop) return 1; |
525 | | |
526 | 0 | if (w1 < w2) return -1; |
527 | 0 | if (w1 > w2) return 1; |
528 | | |
529 | 0 | return 0; |
530 | 0 | } |
531 | | |
532 | | |
533 | 0 | int uv_signal_stop(uv_signal_t* handle) { |
534 | 0 | assert(!uv__is_closing(handle)); |
535 | 0 | uv__signal_stop(handle); |
536 | 0 | return 0; |
537 | 0 | } |
538 | | |
539 | | |
540 | 0 | static void uv__signal_stop(uv_signal_t* handle) { |
541 | 0 | uv_signal_t* removed_handle; |
542 | 0 | sigset_t saved_sigmask; |
543 | 0 | uv_signal_t* first_handle; |
544 | 0 | int rem_oneshot; |
545 | 0 | int first_oneshot; |
546 | 0 | int ret; |
547 | | |
548 | | /* If the watcher wasn't started, this is a no-op. */ |
549 | 0 | if (handle->signum == 0) |
550 | 0 | return; |
551 | | |
552 | 0 | uv__signal_block_and_lock(&saved_sigmask); |
553 | |
|
554 | 0 | removed_handle = RB_REMOVE(uv__signal_tree_s, &uv__signal_tree, handle); |
555 | 0 | assert(removed_handle == handle); |
556 | 0 | (void) removed_handle; |
557 | | |
558 | | /* Check if there are other active signal watchers observing this signal. If |
559 | | * not, unregister the signal handler. |
560 | | */ |
561 | 0 | first_handle = uv__signal_first_handle(handle->signum); |
562 | 0 | if (first_handle == NULL) { |
563 | 0 | uv__signal_unregister_handler(handle->signum); |
564 | 0 | } else { |
565 | 0 | rem_oneshot = handle->flags & UV_SIGNAL_ONE_SHOT; |
566 | 0 | first_oneshot = first_handle->flags & UV_SIGNAL_ONE_SHOT; |
567 | 0 | if (first_oneshot && !rem_oneshot) { |
568 | 0 | ret = uv__signal_register_handler(handle->signum, 1); |
569 | 0 | assert(ret == 0); |
570 | 0 | (void)ret; |
571 | 0 | } |
572 | 0 | } |
573 | |
|
574 | 0 | uv__signal_unlock_and_unblock(&saved_sigmask); |
575 | |
|
576 | 0 | handle->signum = 0; |
577 | 0 | uv__handle_stop(handle); |
578 | 0 | } |