xref: /third_party/libuv/src/unix/signal.c (revision e66f31c5)
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