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