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