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:
9
* The above copyright notice and this permission notice shall be included in
10
* all copies or substantial portions of the Software.
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
37
RB_HEAD(uv__signal_tree_s, uv_signal_s);
40
static int uv__signal_unlock(void);
41
static void uv__signal_event(uv_loop_t* loop, uv__io_t* w, unsigned int events);
42
static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2);
43
static void uv__signal_stop(uv_signal_t* handle);
46
static pthread_once_t uv__signal_global_init_guard = PTHREAD_ONCE_INIT;
47
static struct uv__signal_tree_s uv__signal_tree =
48
RB_INITIALIZER(uv__signal_tree);
49
static int uv__signal_lock_pipefd[2];
52
RB_GENERATE_STATIC(uv__signal_tree_s,
53
uv_signal_s, tree_entry,
57
static void uv__signal_global_init(void) {
58
if (uv__make_pipe(uv__signal_lock_pipefd, 0))
61
if (uv__signal_unlock())
66
void uv__signal_global_once_init(void) {
67
pthread_once(&uv__signal_global_init_guard, uv__signal_global_init);
72
static int uv__signal_lock(void) {
77
r = read(uv__signal_lock_pipefd[0], &data, sizeof data);
78
} while (r < 0 && errno == EINTR);
80
return (r < 0) ? -1 : 0;
84
static int uv__signal_unlock(void) {
89
r = write(uv__signal_lock_pipefd[1], &data, sizeof data);
90
} while (r < 0 && errno == EINTR);
92
return (r < 0) ? -1 : 0;
96
static void uv__signal_block_and_lock(sigset_t* saved_sigmask) {
99
if (sigfillset(&new_mask))
102
if (pthread_sigmask(SIG_SETMASK, &new_mask, saved_sigmask))
105
if (uv__signal_lock())
110
static void uv__signal_unlock_and_unblock(sigset_t* saved_sigmask) {
111
if (uv__signal_unlock())
114
if (pthread_sigmask(SIG_SETMASK, saved_sigmask, NULL))
119
static uv_signal_t* uv__signal_first_handle(int signum) {
120
/* This function must be called with the signal lock held. */
124
lookup.signum = signum;
127
handle = RB_NFIND(uv__signal_tree_s, &uv__signal_tree, &lookup);
129
if (handle != NULL && handle->signum == signum)
136
static void uv__signal_handler(int signum) {
137
uv__signal_msg_t msg;
142
memset(&msg, 0, sizeof msg);
144
if (uv__signal_lock()) {
149
for (handle = uv__signal_first_handle(signum);
150
handle != NULL && handle->signum == signum;
151
handle = RB_NEXT(uv__signal_tree_s, &uv__signal_tree, handle)) {
157
/* write() should be atomic for small data chunks, so the entire message
158
* should be written at once. In theory the pipe could become full, in
159
* which case the user is out of luck.
162
r = write(handle->loop->signal_pipefd[1], &msg, sizeof msg);
163
} while (r == -1 && errno == EINTR);
165
assert(r == sizeof msg ||
166
(r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)));
169
handle->caught_signals++;
177
static int uv__signal_register_handler(int signum) {
178
/* When this function is called, the signal lock must be held. */
181
/* XXX use a separate signal stack? */
182
memset(&sa, 0, sizeof(sa));
183
if (sigfillset(&sa.sa_mask))
185
sa.sa_handler = uv__signal_handler;
187
/* XXX save old action so we can restore it later on? */
188
if (sigaction(signum, &sa, NULL))
195
static void uv__signal_unregister_handler(int signum) {
196
/* When this function is called, the signal lock must be held. */
199
memset(&sa, 0, sizeof(sa));
200
sa.sa_handler = SIG_DFL;
202
/* sigaction can only fail with EINVAL or EFAULT; an attempt to deregister a
203
* signal implies that it was successfully registered earlier, so EINVAL
204
* should never happen.
206
if (sigaction(signum, &sa, NULL))
211
static int uv__signal_loop_once_init(uv_loop_t* loop) {
214
/* Return if already initialized. */
215
if (loop->signal_pipefd[0] != -1)
218
err = uv__make_pipe(loop->signal_pipefd, UV__F_NONBLOCK);
222
uv__io_init(&loop->signal_io_watcher,
224
loop->signal_pipefd[0]);
225
uv__io_start(loop, &loop->signal_io_watcher, UV__POLLIN);
231
void uv__signal_loop_cleanup(uv_loop_t* loop) {
234
/* Stop all the signal watchers that are still attached to this loop. This
235
* ensures that the (shared) signal tree doesn't contain any invalid entries
236
* entries, and that signal handlers are removed when appropriate.
238
QUEUE_FOREACH(q, &loop->handle_queue) {
239
uv_handle_t* handle = QUEUE_DATA(q, uv_handle_t, handle_queue);
241
if (handle->type == UV_SIGNAL)
242
uv__signal_stop((uv_signal_t*) handle);
245
if (loop->signal_pipefd[0] != -1) {
246
uv__close(loop->signal_pipefd[0]);
247
loop->signal_pipefd[0] = -1;
250
if (loop->signal_pipefd[1] != -1) {
251
uv__close(loop->signal_pipefd[1]);
252
loop->signal_pipefd[1] = -1;
257
int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) {
260
err = uv__signal_loop_once_init(loop);
264
uv__handle_init(loop, (uv_handle_t*) handle, UV_SIGNAL);
266
handle->caught_signals = 0;
267
handle->dispatched_signals = 0;
273
void uv__signal_close(uv_signal_t* handle) {
275
uv__signal_stop(handle);
277
/* If there are any caught signals "trapped" in the signal pipe, we can't
278
* call the close callback yet. Otherwise, add the handle to the finish_close
281
if (handle->caught_signals == handle->dispatched_signals) {
282
uv__make_close_pending((uv_handle_t*) handle);
287
int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
288
sigset_t saved_sigmask;
291
assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
293
/* If the user supplies signum == 0, then return an error already. If the
294
* signum is otherwise invalid then uv__signal_register will find out
300
/* Short circuit: if the signal watcher is already watching {signum} don't
301
* go through the process of deregistering and registering the handler.
302
* Additionally, this avoids pending signals getting lost in the small time
303
* time frame that handle->signum == 0.
305
if (signum == handle->signum) {
306
handle->signal_cb = signal_cb;
310
/* If the signal handler was already active, stop it first. */
311
if (handle->signum != 0) {
312
uv__signal_stop(handle);
315
uv__signal_block_and_lock(&saved_sigmask);
317
/* If at this point there are no active signal watchers for this signum (in
318
* any of the loops), it's time to try and register a handler for it here.
320
if (uv__signal_first_handle(signum) == NULL) {
321
err = uv__signal_register_handler(signum);
323
/* Registering the signal handler failed. Must be an invalid signal. */
324
uv__signal_unlock_and_unblock(&saved_sigmask);
329
handle->signum = signum;
330
RB_INSERT(uv__signal_tree_s, &uv__signal_tree, handle);
332
uv__signal_unlock_and_unblock(&saved_sigmask);
334
handle->signal_cb = signal_cb;
335
uv__handle_start(handle);
341
static void uv__signal_event(uv_loop_t* loop,
343
unsigned int events) {
344
uv__signal_msg_t* msg;
346
char buf[sizeof(uv__signal_msg_t) * 32];
347
size_t bytes, end, i;
354
r = read(loop->signal_pipefd[0], buf + bytes, sizeof(buf) - bytes);
356
if (r == -1 && errno == EINTR)
359
if (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
360
/* If there are bytes in the buffer already (which really is extremely
361
* unlikely if possible at all) we can't exit the function here. We'll
362
* spin until more bytes are read instead.
367
/* Otherwise, there was nothing there. */
371
/* Other errors really should never happen. */
377
/* `end` is rounded down to a multiple of sizeof(uv__signal_msg_t). */
378
end = (bytes / sizeof(uv__signal_msg_t)) * sizeof(uv__signal_msg_t);
380
for (i = 0; i < end; i += sizeof(uv__signal_msg_t)) {
381
msg = (uv__signal_msg_t*) (buf + i);
382
handle = msg->handle;
384
if (msg->signum == handle->signum) {
385
assert(!(handle->flags & UV_CLOSING));
386
handle->signal_cb(handle, handle->signum);
389
handle->dispatched_signals++;
391
/* If uv_close was called while there were caught signals that were not
392
* yet dispatched, the uv__finish_close was deferred. Make close pending
393
* now if this has happened.
395
if ((handle->flags & UV_CLOSING) &&
396
(handle->caught_signals == handle->dispatched_signals)) {
397
uv__make_close_pending((uv_handle_t*) handle);
403
/* If there are any "partial" messages left, move them to the start of the
404
* the buffer, and spin. This should not happen.
407
memmove(buf, buf + end, bytes);
410
} while (end == sizeof buf);
414
static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
415
/* Compare signums first so all watchers with the same signnum end up
418
if (w1->signum < w2->signum) return -1;
419
if (w1->signum > w2->signum) return 1;
421
/* Sort by loop pointer, so we can easily look up the first item after
422
* { .signum = x, .loop = NULL }.
424
if (w1->loop < w2->loop) return -1;
425
if (w1->loop > w2->loop) return 1;
427
if (w1 < w2) return -1;
428
if (w1 > w2) return 1;
434
int uv_signal_stop(uv_signal_t* handle) {
435
assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
436
uv__signal_stop(handle);
441
static void uv__signal_stop(uv_signal_t* handle) {
442
uv_signal_t* removed_handle;
443
sigset_t saved_sigmask;
445
/* If the watcher wasn't started, this is a no-op. */
446
if (handle->signum == 0)
449
uv__signal_block_and_lock(&saved_sigmask);
451
removed_handle = RB_REMOVE(uv__signal_tree_s, &uv__signal_tree, handle);
452
assert(removed_handle == handle);
453
(void) removed_handle;
455
/* Check if there are other active signal watchers observing this signal. If
456
* not, unregister the signal handler.
458
if (uv__signal_first_handle(handle->signum) == NULL)
459
uv__signal_unregister_handler(handle->signum);
461
uv__signal_unlock_and_unblock(&saved_sigmask);
464
uv__handle_stop(handle);