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