11cb0ef41Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
21cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
31cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to
41cb0ef41Sopenharmony_ci * deal in the Software without restriction, including without limitation the
51cb0ef41Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
61cb0ef41Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
71cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions:
81cb0ef41Sopenharmony_ci *
91cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
101cb0ef41Sopenharmony_ci * all copies or substantial portions of the Software.
111cb0ef41Sopenharmony_ci *
121cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
131cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
141cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
151cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
161cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
171cb0ef41Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
181cb0ef41Sopenharmony_ci * IN THE SOFTWARE.
191cb0ef41Sopenharmony_ci */
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci#include "uv.h"
221cb0ef41Sopenharmony_ci#include "internal.h"
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci#include <assert.h>
251cb0ef41Sopenharmony_ci#include <errno.h>
261cb0ef41Sopenharmony_ci#include <signal.h>
271cb0ef41Sopenharmony_ci#include <stdlib.h>
281cb0ef41Sopenharmony_ci#include <string.h>
291cb0ef41Sopenharmony_ci#include <unistd.h>
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci#ifndef SA_RESTART
321cb0ef41Sopenharmony_ci# define SA_RESTART 0
331cb0ef41Sopenharmony_ci#endif
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_citypedef struct {
361cb0ef41Sopenharmony_ci  uv_signal_t* handle;
371cb0ef41Sopenharmony_ci  int signum;
381cb0ef41Sopenharmony_ci} uv__signal_msg_t;
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ciRB_HEAD(uv__signal_tree_s, uv_signal_s);
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_cistatic int uv__signal_unlock(void);
441cb0ef41Sopenharmony_cistatic int uv__signal_start(uv_signal_t* handle,
451cb0ef41Sopenharmony_ci                            uv_signal_cb signal_cb,
461cb0ef41Sopenharmony_ci                            int signum,
471cb0ef41Sopenharmony_ci                            int oneshot);
481cb0ef41Sopenharmony_cistatic void uv__signal_event(uv_loop_t* loop, uv__io_t* w, unsigned int events);
491cb0ef41Sopenharmony_cistatic int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2);
501cb0ef41Sopenharmony_cistatic void uv__signal_stop(uv_signal_t* handle);
511cb0ef41Sopenharmony_cistatic void uv__signal_unregister_handler(int signum);
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_cistatic uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT;
551cb0ef41Sopenharmony_cistatic struct uv__signal_tree_s uv__signal_tree =
561cb0ef41Sopenharmony_ci    RB_INITIALIZER(uv__signal_tree);
571cb0ef41Sopenharmony_cistatic int uv__signal_lock_pipefd[2] = { -1, -1 };
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ciRB_GENERATE_STATIC(uv__signal_tree_s,
601cb0ef41Sopenharmony_ci                   uv_signal_s, tree_entry,
611cb0ef41Sopenharmony_ci                   uv__signal_compare)
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_cistatic void uv__signal_global_reinit(void);
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_cistatic void uv__signal_global_init(void) {
661cb0ef41Sopenharmony_ci  if (uv__signal_lock_pipefd[0] == -1)
671cb0ef41Sopenharmony_ci    /* pthread_atfork can register before and after handlers, one
681cb0ef41Sopenharmony_ci     * for each child. This only registers one for the child. That
691cb0ef41Sopenharmony_ci     * state is both persistent and cumulative, so if we keep doing
701cb0ef41Sopenharmony_ci     * it the handler functions will be called multiple times. Thus
711cb0ef41Sopenharmony_ci     * we only want to do it once.
721cb0ef41Sopenharmony_ci     */
731cb0ef41Sopenharmony_ci    if (pthread_atfork(NULL, NULL, &uv__signal_global_reinit))
741cb0ef41Sopenharmony_ci      abort();
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  uv__signal_global_reinit();
771cb0ef41Sopenharmony_ci}
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_civoid uv__signal_cleanup(void) {
811cb0ef41Sopenharmony_ci  /* We can only use signal-safe functions here.
821cb0ef41Sopenharmony_ci   * That includes read/write and close, fortunately.
831cb0ef41Sopenharmony_ci   * We do all of this directly here instead of resetting
841cb0ef41Sopenharmony_ci   * uv__signal_global_init_guard because
851cb0ef41Sopenharmony_ci   * uv__signal_global_once_init is only called from uv_loop_init
861cb0ef41Sopenharmony_ci   * and this needs to function in existing loops.
871cb0ef41Sopenharmony_ci   */
881cb0ef41Sopenharmony_ci  if (uv__signal_lock_pipefd[0] != -1) {
891cb0ef41Sopenharmony_ci    uv__close(uv__signal_lock_pipefd[0]);
901cb0ef41Sopenharmony_ci    uv__signal_lock_pipefd[0] = -1;
911cb0ef41Sopenharmony_ci  }
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci  if (uv__signal_lock_pipefd[1] != -1) {
941cb0ef41Sopenharmony_ci    uv__close(uv__signal_lock_pipefd[1]);
951cb0ef41Sopenharmony_ci    uv__signal_lock_pipefd[1] = -1;
961cb0ef41Sopenharmony_ci  }
971cb0ef41Sopenharmony_ci}
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_cistatic void uv__signal_global_reinit(void) {
1011cb0ef41Sopenharmony_ci  uv__signal_cleanup();
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci  if (uv__make_pipe(uv__signal_lock_pipefd, 0))
1041cb0ef41Sopenharmony_ci    abort();
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  if (uv__signal_unlock())
1071cb0ef41Sopenharmony_ci    abort();
1081cb0ef41Sopenharmony_ci}
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_civoid uv__signal_global_once_init(void) {
1121cb0ef41Sopenharmony_ci  uv_once(&uv__signal_global_init_guard, uv__signal_global_init);
1131cb0ef41Sopenharmony_ci}
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_cistatic int uv__signal_lock(void) {
1171cb0ef41Sopenharmony_ci  int r;
1181cb0ef41Sopenharmony_ci  char data;
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  do {
1211cb0ef41Sopenharmony_ci    r = read(uv__signal_lock_pipefd[0], &data, sizeof data);
1221cb0ef41Sopenharmony_ci  } while (r < 0 && errno == EINTR);
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci  return (r < 0) ? -1 : 0;
1251cb0ef41Sopenharmony_ci}
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_cistatic int uv__signal_unlock(void) {
1291cb0ef41Sopenharmony_ci  int r;
1301cb0ef41Sopenharmony_ci  char data = 42;
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci  do {
1331cb0ef41Sopenharmony_ci    r = write(uv__signal_lock_pipefd[1], &data, sizeof data);
1341cb0ef41Sopenharmony_ci  } while (r < 0 && errno == EINTR);
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci  return (r < 0) ? -1 : 0;
1371cb0ef41Sopenharmony_ci}
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_cistatic void uv__signal_block_and_lock(sigset_t* saved_sigmask) {
1411cb0ef41Sopenharmony_ci  sigset_t new_mask;
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  if (sigfillset(&new_mask))
1441cb0ef41Sopenharmony_ci    abort();
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci  /* to shut up valgrind */
1471cb0ef41Sopenharmony_ci  sigemptyset(saved_sigmask);
1481cb0ef41Sopenharmony_ci  if (pthread_sigmask(SIG_SETMASK, &new_mask, saved_sigmask))
1491cb0ef41Sopenharmony_ci    abort();
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  if (uv__signal_lock())
1521cb0ef41Sopenharmony_ci    abort();
1531cb0ef41Sopenharmony_ci}
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_cistatic void uv__signal_unlock_and_unblock(sigset_t* saved_sigmask) {
1571cb0ef41Sopenharmony_ci  if (uv__signal_unlock())
1581cb0ef41Sopenharmony_ci    abort();
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci  if (pthread_sigmask(SIG_SETMASK, saved_sigmask, NULL))
1611cb0ef41Sopenharmony_ci    abort();
1621cb0ef41Sopenharmony_ci}
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_cistatic uv_signal_t* uv__signal_first_handle(int signum) {
1661cb0ef41Sopenharmony_ci  /* This function must be called with the signal lock held. */
1671cb0ef41Sopenharmony_ci  uv_signal_t lookup;
1681cb0ef41Sopenharmony_ci  uv_signal_t* handle;
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci  lookup.signum = signum;
1711cb0ef41Sopenharmony_ci  lookup.flags = 0;
1721cb0ef41Sopenharmony_ci  lookup.loop = NULL;
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ci  handle = RB_NFIND(uv__signal_tree_s, &uv__signal_tree, &lookup);
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci  if (handle != NULL && handle->signum == signum)
1771cb0ef41Sopenharmony_ci    return handle;
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci  return NULL;
1801cb0ef41Sopenharmony_ci}
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_cistatic void uv__signal_handler(int signum) {
1841cb0ef41Sopenharmony_ci  uv__signal_msg_t msg;
1851cb0ef41Sopenharmony_ci  uv_signal_t* handle;
1861cb0ef41Sopenharmony_ci  int saved_errno;
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_ci  saved_errno = errno;
1891cb0ef41Sopenharmony_ci  memset(&msg, 0, sizeof msg);
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci  if (uv__signal_lock()) {
1921cb0ef41Sopenharmony_ci    errno = saved_errno;
1931cb0ef41Sopenharmony_ci    return;
1941cb0ef41Sopenharmony_ci  }
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci  for (handle = uv__signal_first_handle(signum);
1971cb0ef41Sopenharmony_ci       handle != NULL && handle->signum == signum;
1981cb0ef41Sopenharmony_ci       handle = RB_NEXT(uv__signal_tree_s, &uv__signal_tree, handle)) {
1991cb0ef41Sopenharmony_ci    int r;
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_ci    msg.signum = signum;
2021cb0ef41Sopenharmony_ci    msg.handle = handle;
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ci    /* write() should be atomic for small data chunks, so the entire message
2051cb0ef41Sopenharmony_ci     * should be written at once. In theory the pipe could become full, in
2061cb0ef41Sopenharmony_ci     * which case the user is out of luck.
2071cb0ef41Sopenharmony_ci     */
2081cb0ef41Sopenharmony_ci    do {
2091cb0ef41Sopenharmony_ci      r = write(handle->loop->signal_pipefd[1], &msg, sizeof msg);
2101cb0ef41Sopenharmony_ci    } while (r == -1 && errno == EINTR);
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci    assert(r == sizeof msg ||
2131cb0ef41Sopenharmony_ci           (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)));
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci    if (r != -1)
2161cb0ef41Sopenharmony_ci      handle->caught_signals++;
2171cb0ef41Sopenharmony_ci  }
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci  uv__signal_unlock();
2201cb0ef41Sopenharmony_ci  errno = saved_errno;
2211cb0ef41Sopenharmony_ci}
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_cistatic int uv__signal_register_handler(int signum, int oneshot) {
2251cb0ef41Sopenharmony_ci  /* When this function is called, the signal lock must be held. */
2261cb0ef41Sopenharmony_ci  struct sigaction sa;
2271cb0ef41Sopenharmony_ci
2281cb0ef41Sopenharmony_ci  /* XXX use a separate signal stack? */
2291cb0ef41Sopenharmony_ci  memset(&sa, 0, sizeof(sa));
2301cb0ef41Sopenharmony_ci  if (sigfillset(&sa.sa_mask))
2311cb0ef41Sopenharmony_ci    abort();
2321cb0ef41Sopenharmony_ci  sa.sa_handler = uv__signal_handler;
2331cb0ef41Sopenharmony_ci  sa.sa_flags = SA_RESTART;
2341cb0ef41Sopenharmony_ci  if (oneshot)
2351cb0ef41Sopenharmony_ci    sa.sa_flags |= SA_RESETHAND;
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ci  /* XXX save old action so we can restore it later on? */
2381cb0ef41Sopenharmony_ci  if (sigaction(signum, &sa, NULL))
2391cb0ef41Sopenharmony_ci    return UV__ERR(errno);
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci  return 0;
2421cb0ef41Sopenharmony_ci}
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_cistatic void uv__signal_unregister_handler(int signum) {
2461cb0ef41Sopenharmony_ci  /* When this function is called, the signal lock must be held. */
2471cb0ef41Sopenharmony_ci  struct sigaction sa;
2481cb0ef41Sopenharmony_ci
2491cb0ef41Sopenharmony_ci  memset(&sa, 0, sizeof(sa));
2501cb0ef41Sopenharmony_ci  sa.sa_handler = SIG_DFL;
2511cb0ef41Sopenharmony_ci
2521cb0ef41Sopenharmony_ci  /* sigaction can only fail with EINVAL or EFAULT; an attempt to deregister a
2531cb0ef41Sopenharmony_ci   * signal implies that it was successfully registered earlier, so EINVAL
2541cb0ef41Sopenharmony_ci   * should never happen.
2551cb0ef41Sopenharmony_ci   */
2561cb0ef41Sopenharmony_ci  if (sigaction(signum, &sa, NULL))
2571cb0ef41Sopenharmony_ci    abort();
2581cb0ef41Sopenharmony_ci}
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_ci
2611cb0ef41Sopenharmony_cistatic int uv__signal_loop_once_init(uv_loop_t* loop) {
2621cb0ef41Sopenharmony_ci  int err;
2631cb0ef41Sopenharmony_ci
2641cb0ef41Sopenharmony_ci  /* Return if already initialized. */
2651cb0ef41Sopenharmony_ci  if (loop->signal_pipefd[0] != -1)
2661cb0ef41Sopenharmony_ci    return 0;
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_ci  err = uv__make_pipe(loop->signal_pipefd, UV_NONBLOCK_PIPE);
2691cb0ef41Sopenharmony_ci  if (err)
2701cb0ef41Sopenharmony_ci    return err;
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_ci  uv__io_init(&loop->signal_io_watcher,
2731cb0ef41Sopenharmony_ci              uv__signal_event,
2741cb0ef41Sopenharmony_ci              loop->signal_pipefd[0]);
2751cb0ef41Sopenharmony_ci  uv__io_start(loop, &loop->signal_io_watcher, POLLIN);
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ci  return 0;
2781cb0ef41Sopenharmony_ci}
2791cb0ef41Sopenharmony_ci
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ciint uv__signal_loop_fork(uv_loop_t* loop) {
2821cb0ef41Sopenharmony_ci  uv__io_stop(loop, &loop->signal_io_watcher, POLLIN);
2831cb0ef41Sopenharmony_ci  uv__close(loop->signal_pipefd[0]);
2841cb0ef41Sopenharmony_ci  uv__close(loop->signal_pipefd[1]);
2851cb0ef41Sopenharmony_ci  loop->signal_pipefd[0] = -1;
2861cb0ef41Sopenharmony_ci  loop->signal_pipefd[1] = -1;
2871cb0ef41Sopenharmony_ci  return uv__signal_loop_once_init(loop);
2881cb0ef41Sopenharmony_ci}
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_civoid uv__signal_loop_cleanup(uv_loop_t* loop) {
2921cb0ef41Sopenharmony_ci  QUEUE* q;
2931cb0ef41Sopenharmony_ci
2941cb0ef41Sopenharmony_ci  /* Stop all the signal watchers that are still attached to this loop. This
2951cb0ef41Sopenharmony_ci   * ensures that the (shared) signal tree doesn't contain any invalid entries
2961cb0ef41Sopenharmony_ci   * entries, and that signal handlers are removed when appropriate.
2971cb0ef41Sopenharmony_ci   * It's safe to use QUEUE_FOREACH here because the handles and the handle
2981cb0ef41Sopenharmony_ci   * queue are not modified by uv__signal_stop().
2991cb0ef41Sopenharmony_ci   */
3001cb0ef41Sopenharmony_ci  QUEUE_FOREACH(q, &loop->handle_queue) {
3011cb0ef41Sopenharmony_ci    uv_handle_t* handle = QUEUE_DATA(q, uv_handle_t, handle_queue);
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci    if (handle->type == UV_SIGNAL)
3041cb0ef41Sopenharmony_ci      uv__signal_stop((uv_signal_t*) handle);
3051cb0ef41Sopenharmony_ci  }
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ci  if (loop->signal_pipefd[0] != -1) {
3081cb0ef41Sopenharmony_ci    uv__close(loop->signal_pipefd[0]);
3091cb0ef41Sopenharmony_ci    loop->signal_pipefd[0] = -1;
3101cb0ef41Sopenharmony_ci  }
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_ci  if (loop->signal_pipefd[1] != -1) {
3131cb0ef41Sopenharmony_ci    uv__close(loop->signal_pipefd[1]);
3141cb0ef41Sopenharmony_ci    loop->signal_pipefd[1] = -1;
3151cb0ef41Sopenharmony_ci  }
3161cb0ef41Sopenharmony_ci}
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_ciint uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) {
3201cb0ef41Sopenharmony_ci  int err;
3211cb0ef41Sopenharmony_ci
3221cb0ef41Sopenharmony_ci  err = uv__signal_loop_once_init(loop);
3231cb0ef41Sopenharmony_ci  if (err)
3241cb0ef41Sopenharmony_ci    return err;
3251cb0ef41Sopenharmony_ci
3261cb0ef41Sopenharmony_ci  uv__handle_init(loop, (uv_handle_t*) handle, UV_SIGNAL);
3271cb0ef41Sopenharmony_ci  handle->signum = 0;
3281cb0ef41Sopenharmony_ci  handle->caught_signals = 0;
3291cb0ef41Sopenharmony_ci  handle->dispatched_signals = 0;
3301cb0ef41Sopenharmony_ci
3311cb0ef41Sopenharmony_ci  return 0;
3321cb0ef41Sopenharmony_ci}
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_civoid uv__signal_close(uv_signal_t* handle) {
3361cb0ef41Sopenharmony_ci  uv__signal_stop(handle);
3371cb0ef41Sopenharmony_ci}
3381cb0ef41Sopenharmony_ci
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ciint uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
3411cb0ef41Sopenharmony_ci  return uv__signal_start(handle, signal_cb, signum, 0);
3421cb0ef41Sopenharmony_ci}
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_ci
3451cb0ef41Sopenharmony_ciint uv_signal_start_oneshot(uv_signal_t* handle,
3461cb0ef41Sopenharmony_ci                            uv_signal_cb signal_cb,
3471cb0ef41Sopenharmony_ci                            int signum) {
3481cb0ef41Sopenharmony_ci  return uv__signal_start(handle, signal_cb, signum, 1);
3491cb0ef41Sopenharmony_ci}
3501cb0ef41Sopenharmony_ci
3511cb0ef41Sopenharmony_ci
3521cb0ef41Sopenharmony_cistatic int uv__signal_start(uv_signal_t* handle,
3531cb0ef41Sopenharmony_ci                            uv_signal_cb signal_cb,
3541cb0ef41Sopenharmony_ci                            int signum,
3551cb0ef41Sopenharmony_ci                            int oneshot) {
3561cb0ef41Sopenharmony_ci  sigset_t saved_sigmask;
3571cb0ef41Sopenharmony_ci  int err;
3581cb0ef41Sopenharmony_ci  uv_signal_t* first_handle;
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ci  assert(!uv__is_closing(handle));
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_ci  /* If the user supplies signum == 0, then return an error already. If the
3631cb0ef41Sopenharmony_ci   * signum is otherwise invalid then uv__signal_register will find out
3641cb0ef41Sopenharmony_ci   * eventually.
3651cb0ef41Sopenharmony_ci   */
3661cb0ef41Sopenharmony_ci  if (signum == 0)
3671cb0ef41Sopenharmony_ci    return UV_EINVAL;
3681cb0ef41Sopenharmony_ci
3691cb0ef41Sopenharmony_ci  /* Short circuit: if the signal watcher is already watching {signum} don't
3701cb0ef41Sopenharmony_ci   * go through the process of deregistering and registering the handler.
3711cb0ef41Sopenharmony_ci   * Additionally, this avoids pending signals getting lost in the small
3721cb0ef41Sopenharmony_ci   * time frame that handle->signum == 0.
3731cb0ef41Sopenharmony_ci   */
3741cb0ef41Sopenharmony_ci  if (signum == handle->signum) {
3751cb0ef41Sopenharmony_ci    handle->signal_cb = signal_cb;
3761cb0ef41Sopenharmony_ci    return 0;
3771cb0ef41Sopenharmony_ci  }
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_ci  /* If the signal handler was already active, stop it first. */
3801cb0ef41Sopenharmony_ci  if (handle->signum != 0) {
3811cb0ef41Sopenharmony_ci    uv__signal_stop(handle);
3821cb0ef41Sopenharmony_ci  }
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ci  uv__signal_block_and_lock(&saved_sigmask);
3851cb0ef41Sopenharmony_ci
3861cb0ef41Sopenharmony_ci  /* If at this point there are no active signal watchers for this signum (in
3871cb0ef41Sopenharmony_ci   * any of the loops), it's time to try and register a handler for it here.
3881cb0ef41Sopenharmony_ci   * Also in case there's only one-shot handlers and a regular handler comes in.
3891cb0ef41Sopenharmony_ci   */
3901cb0ef41Sopenharmony_ci  first_handle = uv__signal_first_handle(signum);
3911cb0ef41Sopenharmony_ci  if (first_handle == NULL ||
3921cb0ef41Sopenharmony_ci      (!oneshot && (first_handle->flags & UV_SIGNAL_ONE_SHOT))) {
3931cb0ef41Sopenharmony_ci    err = uv__signal_register_handler(signum, oneshot);
3941cb0ef41Sopenharmony_ci    if (err) {
3951cb0ef41Sopenharmony_ci      /* Registering the signal handler failed. Must be an invalid signal. */
3961cb0ef41Sopenharmony_ci      uv__signal_unlock_and_unblock(&saved_sigmask);
3971cb0ef41Sopenharmony_ci      return err;
3981cb0ef41Sopenharmony_ci    }
3991cb0ef41Sopenharmony_ci  }
4001cb0ef41Sopenharmony_ci
4011cb0ef41Sopenharmony_ci  handle->signum = signum;
4021cb0ef41Sopenharmony_ci  if (oneshot)
4031cb0ef41Sopenharmony_ci    handle->flags |= UV_SIGNAL_ONE_SHOT;
4041cb0ef41Sopenharmony_ci
4051cb0ef41Sopenharmony_ci  RB_INSERT(uv__signal_tree_s, &uv__signal_tree, handle);
4061cb0ef41Sopenharmony_ci
4071cb0ef41Sopenharmony_ci  uv__signal_unlock_and_unblock(&saved_sigmask);
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci  handle->signal_cb = signal_cb;
4101cb0ef41Sopenharmony_ci  uv__handle_start(handle);
4111cb0ef41Sopenharmony_ci
4121cb0ef41Sopenharmony_ci  return 0;
4131cb0ef41Sopenharmony_ci}
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_ci
4161cb0ef41Sopenharmony_cistatic void uv__signal_event(uv_loop_t* loop,
4171cb0ef41Sopenharmony_ci                             uv__io_t* w,
4181cb0ef41Sopenharmony_ci                             unsigned int events) {
4191cb0ef41Sopenharmony_ci  uv__signal_msg_t* msg;
4201cb0ef41Sopenharmony_ci  uv_signal_t* handle;
4211cb0ef41Sopenharmony_ci  char buf[sizeof(uv__signal_msg_t) * 32];
4221cb0ef41Sopenharmony_ci  size_t bytes, end, i;
4231cb0ef41Sopenharmony_ci  int r;
4241cb0ef41Sopenharmony_ci
4251cb0ef41Sopenharmony_ci  bytes = 0;
4261cb0ef41Sopenharmony_ci  end = 0;
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_ci  do {
4291cb0ef41Sopenharmony_ci    r = read(loop->signal_pipefd[0], buf + bytes, sizeof(buf) - bytes);
4301cb0ef41Sopenharmony_ci
4311cb0ef41Sopenharmony_ci    if (r == -1 && errno == EINTR)
4321cb0ef41Sopenharmony_ci      continue;
4331cb0ef41Sopenharmony_ci
4341cb0ef41Sopenharmony_ci    if (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
4351cb0ef41Sopenharmony_ci      /* If there are bytes in the buffer already (which really is extremely
4361cb0ef41Sopenharmony_ci       * unlikely if possible at all) we can't exit the function here. We'll
4371cb0ef41Sopenharmony_ci       * spin until more bytes are read instead.
4381cb0ef41Sopenharmony_ci       */
4391cb0ef41Sopenharmony_ci      if (bytes > 0)
4401cb0ef41Sopenharmony_ci        continue;
4411cb0ef41Sopenharmony_ci
4421cb0ef41Sopenharmony_ci      /* Otherwise, there was nothing there. */
4431cb0ef41Sopenharmony_ci      return;
4441cb0ef41Sopenharmony_ci    }
4451cb0ef41Sopenharmony_ci
4461cb0ef41Sopenharmony_ci    /* Other errors really should never happen. */
4471cb0ef41Sopenharmony_ci    if (r == -1)
4481cb0ef41Sopenharmony_ci      abort();
4491cb0ef41Sopenharmony_ci
4501cb0ef41Sopenharmony_ci    bytes += r;
4511cb0ef41Sopenharmony_ci
4521cb0ef41Sopenharmony_ci    /* `end` is rounded down to a multiple of sizeof(uv__signal_msg_t). */
4531cb0ef41Sopenharmony_ci    end = (bytes / sizeof(uv__signal_msg_t)) * sizeof(uv__signal_msg_t);
4541cb0ef41Sopenharmony_ci
4551cb0ef41Sopenharmony_ci    for (i = 0; i < end; i += sizeof(uv__signal_msg_t)) {
4561cb0ef41Sopenharmony_ci      msg = (uv__signal_msg_t*) (buf + i);
4571cb0ef41Sopenharmony_ci      handle = msg->handle;
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_ci      if (msg->signum == handle->signum) {
4601cb0ef41Sopenharmony_ci        assert(!(handle->flags & UV_HANDLE_CLOSING));
4611cb0ef41Sopenharmony_ci        handle->signal_cb(handle, handle->signum);
4621cb0ef41Sopenharmony_ci      }
4631cb0ef41Sopenharmony_ci
4641cb0ef41Sopenharmony_ci      handle->dispatched_signals++;
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_ci      if (handle->flags & UV_SIGNAL_ONE_SHOT)
4671cb0ef41Sopenharmony_ci        uv__signal_stop(handle);
4681cb0ef41Sopenharmony_ci    }
4691cb0ef41Sopenharmony_ci
4701cb0ef41Sopenharmony_ci    bytes -= end;
4711cb0ef41Sopenharmony_ci
4721cb0ef41Sopenharmony_ci    /* If there are any "partial" messages left, move them to the start of the
4731cb0ef41Sopenharmony_ci     * the buffer, and spin. This should not happen.
4741cb0ef41Sopenharmony_ci     */
4751cb0ef41Sopenharmony_ci    if (bytes) {
4761cb0ef41Sopenharmony_ci      memmove(buf, buf + end, bytes);
4771cb0ef41Sopenharmony_ci      continue;
4781cb0ef41Sopenharmony_ci    }
4791cb0ef41Sopenharmony_ci  } while (end == sizeof buf);
4801cb0ef41Sopenharmony_ci}
4811cb0ef41Sopenharmony_ci
4821cb0ef41Sopenharmony_ci
4831cb0ef41Sopenharmony_cistatic int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
4841cb0ef41Sopenharmony_ci  int f1;
4851cb0ef41Sopenharmony_ci  int f2;
4861cb0ef41Sopenharmony_ci  /* Compare signums first so all watchers with the same signnum end up
4871cb0ef41Sopenharmony_ci   * adjacent.
4881cb0ef41Sopenharmony_ci   */
4891cb0ef41Sopenharmony_ci  if (w1->signum < w2->signum) return -1;
4901cb0ef41Sopenharmony_ci  if (w1->signum > w2->signum) return 1;
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_ci  /* Handlers without UV_SIGNAL_ONE_SHOT set will come first, so if the first
4931cb0ef41Sopenharmony_ci   * handler returned is a one-shot handler, the rest will be too.
4941cb0ef41Sopenharmony_ci   */
4951cb0ef41Sopenharmony_ci  f1 = w1->flags & UV_SIGNAL_ONE_SHOT;
4961cb0ef41Sopenharmony_ci  f2 = w2->flags & UV_SIGNAL_ONE_SHOT;
4971cb0ef41Sopenharmony_ci  if (f1 < f2) return -1;
4981cb0ef41Sopenharmony_ci  if (f1 > f2) return 1;
4991cb0ef41Sopenharmony_ci
5001cb0ef41Sopenharmony_ci  /* Sort by loop pointer, so we can easily look up the first item after
5011cb0ef41Sopenharmony_ci   * { .signum = x, .loop = NULL }.
5021cb0ef41Sopenharmony_ci   */
5031cb0ef41Sopenharmony_ci  if (w1->loop < w2->loop) return -1;
5041cb0ef41Sopenharmony_ci  if (w1->loop > w2->loop) return 1;
5051cb0ef41Sopenharmony_ci
5061cb0ef41Sopenharmony_ci  if (w1 < w2) return -1;
5071cb0ef41Sopenharmony_ci  if (w1 > w2) return 1;
5081cb0ef41Sopenharmony_ci
5091cb0ef41Sopenharmony_ci  return 0;
5101cb0ef41Sopenharmony_ci}
5111cb0ef41Sopenharmony_ci
5121cb0ef41Sopenharmony_ci
5131cb0ef41Sopenharmony_ciint uv_signal_stop(uv_signal_t* handle) {
5141cb0ef41Sopenharmony_ci  assert(!uv__is_closing(handle));
5151cb0ef41Sopenharmony_ci  uv__signal_stop(handle);
5161cb0ef41Sopenharmony_ci  return 0;
5171cb0ef41Sopenharmony_ci}
5181cb0ef41Sopenharmony_ci
5191cb0ef41Sopenharmony_ci
5201cb0ef41Sopenharmony_cistatic void uv__signal_stop(uv_signal_t* handle) {
5211cb0ef41Sopenharmony_ci  uv_signal_t* removed_handle;
5221cb0ef41Sopenharmony_ci  sigset_t saved_sigmask;
5231cb0ef41Sopenharmony_ci  uv_signal_t* first_handle;
5241cb0ef41Sopenharmony_ci  int rem_oneshot;
5251cb0ef41Sopenharmony_ci  int first_oneshot;
5261cb0ef41Sopenharmony_ci  int ret;
5271cb0ef41Sopenharmony_ci
5281cb0ef41Sopenharmony_ci  /* If the watcher wasn't started, this is a no-op. */
5291cb0ef41Sopenharmony_ci  if (handle->signum == 0)
5301cb0ef41Sopenharmony_ci    return;
5311cb0ef41Sopenharmony_ci
5321cb0ef41Sopenharmony_ci  uv__signal_block_and_lock(&saved_sigmask);
5331cb0ef41Sopenharmony_ci
5341cb0ef41Sopenharmony_ci  removed_handle = RB_REMOVE(uv__signal_tree_s, &uv__signal_tree, handle);
5351cb0ef41Sopenharmony_ci  assert(removed_handle == handle);
5361cb0ef41Sopenharmony_ci  (void) removed_handle;
5371cb0ef41Sopenharmony_ci
5381cb0ef41Sopenharmony_ci  /* Check if there are other active signal watchers observing this signal. If
5391cb0ef41Sopenharmony_ci   * not, unregister the signal handler.
5401cb0ef41Sopenharmony_ci   */
5411cb0ef41Sopenharmony_ci  first_handle = uv__signal_first_handle(handle->signum);
5421cb0ef41Sopenharmony_ci  if (first_handle == NULL) {
5431cb0ef41Sopenharmony_ci    uv__signal_unregister_handler(handle->signum);
5441cb0ef41Sopenharmony_ci  } else {
5451cb0ef41Sopenharmony_ci    rem_oneshot = handle->flags & UV_SIGNAL_ONE_SHOT;
5461cb0ef41Sopenharmony_ci    first_oneshot = first_handle->flags & UV_SIGNAL_ONE_SHOT;
5471cb0ef41Sopenharmony_ci    if (first_oneshot && !rem_oneshot) {
5481cb0ef41Sopenharmony_ci      ret = uv__signal_register_handler(handle->signum, 1);
5491cb0ef41Sopenharmony_ci      assert(ret == 0);
5501cb0ef41Sopenharmony_ci      (void)ret;
5511cb0ef41Sopenharmony_ci    }
5521cb0ef41Sopenharmony_ci  }
5531cb0ef41Sopenharmony_ci
5541cb0ef41Sopenharmony_ci  uv__signal_unlock_and_unblock(&saved_sigmask);
5551cb0ef41Sopenharmony_ci
5561cb0ef41Sopenharmony_ci  handle->signum = 0;
5571cb0ef41Sopenharmony_ci  uv__handle_stop(handle);
5581cb0ef41Sopenharmony_ci}
559