~webapps/unity-js-scopes/node.js

« back to all changes in this revision

Viewing changes to deps/uv/src/unix/signal.c

  • Committer: Marcus Tomlinson
  • Date: 2015-11-13 07:59:04 UTC
  • Revision ID: marcus.tomlinson@canonical.com-20151113075904-h0swczmoq1rvstfc
Node v4 (stable)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
32
typedef struct {
 
33
  uv_signal_t* handle;
 
34
  int signum;
 
35
} uv__signal_msg_t;
 
36
 
 
37
RB_HEAD(uv__signal_tree_s, uv_signal_s);
 
38
 
 
39
 
 
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);
 
44
 
 
45
 
 
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];
 
50
 
 
51
 
 
52
RB_GENERATE_STATIC(uv__signal_tree_s,
 
53
                   uv_signal_s, tree_entry,
 
54
                   uv__signal_compare)
 
55
 
 
56
 
 
57
static void uv__signal_global_init(void) {
 
58
  if (uv__make_pipe(uv__signal_lock_pipefd, 0))
 
59
    abort();
 
60
 
 
61
  if (uv__signal_unlock())
 
62
    abort();
 
63
}
 
64
 
 
65
 
 
66
void uv__signal_global_once_init(void) {
 
67
  pthread_once(&uv__signal_global_init_guard, uv__signal_global_init);
 
68
}
 
69
 
 
70
 
 
71
 
 
72
static int uv__signal_lock(void) {
 
73
  int r;
 
74
  char data;
 
75
 
 
76
  do {
 
77
    r = read(uv__signal_lock_pipefd[0], &data, sizeof data);
 
78
  } while (r < 0 && errno == EINTR);
 
79
 
 
80
  return (r < 0) ? -1 : 0;
 
81
}
 
82
 
 
83
 
 
84
static int uv__signal_unlock(void) {
 
85
  int r;
 
86
  char data = 42;
 
87
 
 
88
  do {
 
89
    r = write(uv__signal_lock_pipefd[1], &data, sizeof data);
 
90
  } while (r < 0 && errno == EINTR);
 
91
 
 
92
  return (r < 0) ? -1 : 0;
 
93
}
 
94
 
 
95
 
 
96
static void uv__signal_block_and_lock(sigset_t* saved_sigmask) {
 
97
  sigset_t new_mask;
 
98
 
 
99
  if (sigfillset(&new_mask))
 
100
    abort();
 
101
 
 
102
  if (pthread_sigmask(SIG_SETMASK, &new_mask, saved_sigmask))
 
103
    abort();
 
104
 
 
105
  if (uv__signal_lock())
 
106
    abort();
 
107
}
 
108
 
 
109
 
 
110
static void uv__signal_unlock_and_unblock(sigset_t* saved_sigmask) {
 
111
  if (uv__signal_unlock())
 
112
    abort();
 
113
 
 
114
  if (pthread_sigmask(SIG_SETMASK, saved_sigmask, NULL))
 
115
    abort();
 
116
}
 
117
 
 
118
 
 
119
static uv_signal_t* uv__signal_first_handle(int signum) {
 
120
  /* This function must be called with the signal lock held. */
 
121
  uv_signal_t lookup;
 
122
  uv_signal_t* handle;
 
123
 
 
124
  lookup.signum = signum;
 
125
  lookup.loop = NULL;
 
126
 
 
127
  handle = RB_NFIND(uv__signal_tree_s, &uv__signal_tree, &lookup);
 
128
 
 
129
  if (handle != NULL && handle->signum == signum)
 
130
    return handle;
 
131
 
 
132
  return NULL;
 
133
}
 
134
 
 
135
 
 
136
static void uv__signal_handler(int signum) {
 
137
  uv__signal_msg_t msg;
 
138
  uv_signal_t* handle;
 
139
  int saved_errno;
 
140
 
 
141
  saved_errno = errno;
 
142
  memset(&msg, 0, sizeof msg);
 
143
 
 
144
  if (uv__signal_lock()) {
 
145
    errno = saved_errno;
 
146
    return;
 
147
  }
 
148
 
 
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)) {
 
152
    int r;
 
153
 
 
154
    msg.signum = signum;
 
155
    msg.handle = handle;
 
156
 
 
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.
 
160
     */
 
161
    do {
 
162
      r = write(handle->loop->signal_pipefd[1], &msg, sizeof msg);
 
163
    } while (r == -1 && errno == EINTR);
 
164
 
 
165
    assert(r == sizeof msg ||
 
166
           (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)));
 
167
 
 
168
    if (r != -1)
 
169
      handle->caught_signals++;
 
170
  }
 
171
 
 
172
  uv__signal_unlock();
 
173
  errno = saved_errno;
 
174
}
 
175
 
 
176
 
 
177
static int uv__signal_register_handler(int signum) {
 
178
  /* When this function is called, the signal lock must be held. */
 
179
  struct sigaction sa;
 
180
 
 
181
  /* XXX use a separate signal stack? */
 
182
  memset(&sa, 0, sizeof(sa));
 
183
  if (sigfillset(&sa.sa_mask))
 
184
    abort();
 
185
  sa.sa_handler = uv__signal_handler;
 
186
 
 
187
  /* XXX save old action so we can restore it later on? */
 
188
  if (sigaction(signum, &sa, NULL))
 
189
    return -errno;
 
190
 
 
191
  return 0;
 
192
}
 
193
 
 
194
 
 
195
static void uv__signal_unregister_handler(int signum) {
 
196
  /* When this function is called, the signal lock must be held. */
 
197
  struct sigaction sa;
 
198
 
 
199
  memset(&sa, 0, sizeof(sa));
 
200
  sa.sa_handler = SIG_DFL;
 
201
 
 
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.
 
205
   */
 
206
  if (sigaction(signum, &sa, NULL))
 
207
    abort();
 
208
}
 
209
 
 
210
 
 
211
static int uv__signal_loop_once_init(uv_loop_t* loop) {
 
212
  int err;
 
213
 
 
214
  /* Return if already initialized. */
 
215
  if (loop->signal_pipefd[0] != -1)
 
216
    return 0;
 
217
 
 
218
  err = uv__make_pipe(loop->signal_pipefd, UV__F_NONBLOCK);
 
219
  if (err)
 
220
    return err;
 
221
 
 
222
  uv__io_init(&loop->signal_io_watcher,
 
223
              uv__signal_event,
 
224
              loop->signal_pipefd[0]);
 
225
  uv__io_start(loop, &loop->signal_io_watcher, UV__POLLIN);
 
226
 
 
227
  return 0;
 
228
}
 
229
 
 
230
 
 
231
void uv__signal_loop_cleanup(uv_loop_t* loop) {
 
232
  QUEUE* q;
 
233
 
 
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.
 
237
   */
 
238
  QUEUE_FOREACH(q, &loop->handle_queue) {
 
239
    uv_handle_t* handle = QUEUE_DATA(q, uv_handle_t, handle_queue);
 
240
 
 
241
    if (handle->type == UV_SIGNAL)
 
242
      uv__signal_stop((uv_signal_t*) handle);
 
243
  }
 
244
 
 
245
  if (loop->signal_pipefd[0] != -1) {
 
246
    uv__close(loop->signal_pipefd[0]);
 
247
    loop->signal_pipefd[0] = -1;
 
248
  }
 
249
 
 
250
  if (loop->signal_pipefd[1] != -1) {
 
251
    uv__close(loop->signal_pipefd[1]);
 
252
    loop->signal_pipefd[1] = -1;
 
253
  }
 
254
}
 
255
 
 
256
 
 
257
int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) {
 
258
  int err;
 
259
 
 
260
  err = uv__signal_loop_once_init(loop);
 
261
  if (err)
 
262
    return err;
 
263
 
 
264
  uv__handle_init(loop, (uv_handle_t*) handle, UV_SIGNAL);
 
265
  handle->signum = 0;
 
266
  handle->caught_signals = 0;
 
267
  handle->dispatched_signals = 0;
 
268
 
 
269
  return 0;
 
270
}
 
271
 
 
272
 
 
273
void uv__signal_close(uv_signal_t* handle) {
 
274
 
 
275
  uv__signal_stop(handle);
 
276
 
 
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
 
279
   * queue.
 
280
   */
 
281
  if (handle->caught_signals == handle->dispatched_signals) {
 
282
    uv__make_close_pending((uv_handle_t*) handle);
 
283
  }
 
284
}
 
285
 
 
286
 
 
287
int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
 
288
  sigset_t saved_sigmask;
 
289
  int err;
 
290
 
 
291
  assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
 
292
 
 
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
 
295
   * eventually.
 
296
   */
 
297
  if (signum == 0)
 
298
    return -EINVAL;
 
299
 
 
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.
 
304
   */
 
305
  if (signum == handle->signum) {
 
306
    handle->signal_cb = signal_cb;
 
307
    return 0;
 
308
  }
 
309
 
 
310
  /* If the signal handler was already active, stop it first. */
 
311
  if (handle->signum != 0) {
 
312
    uv__signal_stop(handle);
 
313
  }
 
314
 
 
315
  uv__signal_block_and_lock(&saved_sigmask);
 
316
 
 
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.
 
319
   */
 
320
  if (uv__signal_first_handle(signum) == NULL) {
 
321
    err = uv__signal_register_handler(signum);
 
322
    if (err) {
 
323
      /* Registering the signal handler failed. Must be an invalid signal. */
 
324
      uv__signal_unlock_and_unblock(&saved_sigmask);
 
325
      return err;
 
326
    }
 
327
  }
 
328
 
 
329
  handle->signum = signum;
 
330
  RB_INSERT(uv__signal_tree_s, &uv__signal_tree, handle);
 
331
 
 
332
  uv__signal_unlock_and_unblock(&saved_sigmask);
 
333
 
 
334
  handle->signal_cb = signal_cb;
 
335
  uv__handle_start(handle);
 
336
 
 
337
  return 0;
 
338
}
 
339
 
 
340
 
 
341
static void uv__signal_event(uv_loop_t* loop,
 
342
                             uv__io_t* w,
 
343
                             unsigned int events) {
 
344
  uv__signal_msg_t* msg;
 
345
  uv_signal_t* handle;
 
346
  char buf[sizeof(uv__signal_msg_t) * 32];
 
347
  size_t bytes, end, i;
 
348
  int r;
 
349
 
 
350
  bytes = 0;
 
351
  end = 0;
 
352
 
 
353
  do {
 
354
    r = read(loop->signal_pipefd[0], buf + bytes, sizeof(buf) - bytes);
 
355
 
 
356
    if (r == -1 && errno == EINTR)
 
357
      continue;
 
358
 
 
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.
 
363
       */
 
364
      if (bytes > 0)
 
365
        continue;
 
366
 
 
367
      /* Otherwise, there was nothing there. */
 
368
      return;
 
369
    }
 
370
 
 
371
    /* Other errors really should never happen. */
 
372
    if (r == -1)
 
373
      abort();
 
374
 
 
375
    bytes += r;
 
376
 
 
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);
 
379
 
 
380
    for (i = 0; i < end; i += sizeof(uv__signal_msg_t)) {
 
381
      msg = (uv__signal_msg_t*) (buf + i);
 
382
      handle = msg->handle;
 
383
 
 
384
      if (msg->signum == handle->signum) {
 
385
        assert(!(handle->flags & UV_CLOSING));
 
386
        handle->signal_cb(handle, handle->signum);
 
387
      }
 
388
 
 
389
      handle->dispatched_signals++;
 
390
 
 
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.
 
394
       */
 
395
      if ((handle->flags & UV_CLOSING) &&
 
396
          (handle->caught_signals == handle->dispatched_signals)) {
 
397
        uv__make_close_pending((uv_handle_t*) handle);
 
398
      }
 
399
    }
 
400
 
 
401
    bytes -= end;
 
402
 
 
403
    /* If there are any "partial" messages left, move them to the start of the
 
404
     * the buffer, and spin. This should not happen.
 
405
     */
 
406
    if (bytes) {
 
407
      memmove(buf, buf + end, bytes);
 
408
      continue;
 
409
    }
 
410
  } while (end == sizeof buf);
 
411
}
 
412
 
 
413
 
 
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
 
416
   * adjacent.
 
417
   */
 
418
  if (w1->signum < w2->signum) return -1;
 
419
  if (w1->signum > w2->signum) return 1;
 
420
 
 
421
  /* Sort by loop pointer, so we can easily look up the first item after
 
422
   * { .signum = x, .loop = NULL }.
 
423
   */
 
424
  if (w1->loop < w2->loop) return -1;
 
425
  if (w1->loop > w2->loop) return 1;
 
426
 
 
427
  if (w1 < w2) return -1;
 
428
  if (w1 > w2) return 1;
 
429
 
 
430
  return 0;
 
431
}
 
432
 
 
433
 
 
434
int uv_signal_stop(uv_signal_t* handle) {
 
435
  assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
 
436
  uv__signal_stop(handle);
 
437
  return 0;
 
438
}
 
439
 
 
440
 
 
441
static void uv__signal_stop(uv_signal_t* handle) {
 
442
  uv_signal_t* removed_handle;
 
443
  sigset_t saved_sigmask;
 
444
 
 
445
  /* If the watcher wasn't started, this is a no-op. */
 
446
  if (handle->signum == 0)
 
447
    return;
 
448
 
 
449
  uv__signal_block_and_lock(&saved_sigmask);
 
450
 
 
451
  removed_handle = RB_REMOVE(uv__signal_tree_s, &uv__signal_tree, handle);
 
452
  assert(removed_handle == handle);
 
453
  (void) removed_handle;
 
454
 
 
455
  /* Check if there are other active signal watchers observing this signal. If
 
456
   * not, unregister the signal handler.
 
457
   */
 
458
  if (uv__signal_first_handle(handle->signum) == NULL)
 
459
    uv__signal_unregister_handler(handle->signum);
 
460
 
 
461
  uv__signal_unlock_and_unblock(&saved_sigmask);
 
462
 
 
463
  handle->signum = 0;
 
464
  uv__handle_stop(handle);
 
465
}