1e66f31c5Sopenharmony_ci/* Copyright libuv project contributors. All rights reserved.
2e66f31c5Sopenharmony_ci *
3e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
4e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to
5e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the
6e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
8e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions:
9e66f31c5Sopenharmony_ci *
10e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
11e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software.
12e66f31c5Sopenharmony_ci *
13e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19e66f31c5Sopenharmony_ci * IN THE SOFTWARE.
20e66f31c5Sopenharmony_ci */
21e66f31c5Sopenharmony_ci
22e66f31c5Sopenharmony_ci/* These tests are Unix only. */
23e66f31c5Sopenharmony_ci#ifndef _WIN32
24e66f31c5Sopenharmony_ci
25e66f31c5Sopenharmony_ci#include <unistd.h>
26e66f31c5Sopenharmony_ci#include <sys/wait.h>
27e66f31c5Sopenharmony_ci#include <sys/socket.h>
28e66f31c5Sopenharmony_ci#include <string.h>
29e66f31c5Sopenharmony_ci
30e66f31c5Sopenharmony_ci#ifdef __APPLE__
31e66f31c5Sopenharmony_ci#include <TargetConditionals.h>
32e66f31c5Sopenharmony_ci#endif
33e66f31c5Sopenharmony_ci
34e66f31c5Sopenharmony_ci#include "uv.h"
35e66f31c5Sopenharmony_ci#include "task.h"
36e66f31c5Sopenharmony_ci
37e66f31c5Sopenharmony_cistatic int timer_cb_called;
38e66f31c5Sopenharmony_cistatic int socket_cb_called;
39e66f31c5Sopenharmony_ci
40e66f31c5Sopenharmony_cistatic void timer_cb(uv_timer_t* timer) {
41e66f31c5Sopenharmony_ci  timer_cb_called++;
42e66f31c5Sopenharmony_ci  uv_close((uv_handle_t*) timer, NULL);
43e66f31c5Sopenharmony_ci}
44e66f31c5Sopenharmony_ci
45e66f31c5Sopenharmony_ci
46e66f31c5Sopenharmony_cistatic int socket_cb_read_fd;
47e66f31c5Sopenharmony_cistatic int socket_cb_read_size;
48e66f31c5Sopenharmony_cistatic char socket_cb_read_buf[1024];
49e66f31c5Sopenharmony_ci
50e66f31c5Sopenharmony_ci
51e66f31c5Sopenharmony_cistatic void socket_cb(uv_poll_t* poll, int status, int events) {
52e66f31c5Sopenharmony_ci  ssize_t cnt;
53e66f31c5Sopenharmony_ci  socket_cb_called++;
54e66f31c5Sopenharmony_ci  ASSERT_OK(status);
55e66f31c5Sopenharmony_ci  printf("Socket cb got events %d\n", events);
56e66f31c5Sopenharmony_ci  ASSERT_EQ(UV_READABLE, (events & UV_READABLE));
57e66f31c5Sopenharmony_ci  if (socket_cb_read_fd) {
58e66f31c5Sopenharmony_ci    cnt = read(socket_cb_read_fd, socket_cb_read_buf, socket_cb_read_size);
59e66f31c5Sopenharmony_ci    ASSERT_EQ(cnt, socket_cb_read_size);
60e66f31c5Sopenharmony_ci  }
61e66f31c5Sopenharmony_ci  uv_close((uv_handle_t*) poll, NULL);
62e66f31c5Sopenharmony_ci}
63e66f31c5Sopenharmony_ci
64e66f31c5Sopenharmony_ci
65e66f31c5Sopenharmony_cistatic void run_timer_loop_once(void) {
66e66f31c5Sopenharmony_ci  uv_loop_t loop;
67e66f31c5Sopenharmony_ci  uv_timer_t timer_handle;
68e66f31c5Sopenharmony_ci
69e66f31c5Sopenharmony_ci  ASSERT_OK(uv_loop_init(&loop));
70e66f31c5Sopenharmony_ci
71e66f31c5Sopenharmony_ci  timer_cb_called = 0; /* Reset for the child. */
72e66f31c5Sopenharmony_ci
73e66f31c5Sopenharmony_ci  ASSERT_OK(uv_timer_init(&loop, &timer_handle));
74e66f31c5Sopenharmony_ci  ASSERT_OK(uv_timer_start(&timer_handle, timer_cb, 1, 0));
75e66f31c5Sopenharmony_ci  ASSERT_OK(uv_run(&loop, UV_RUN_DEFAULT));
76e66f31c5Sopenharmony_ci  ASSERT_EQ(1, timer_cb_called);
77e66f31c5Sopenharmony_ci  ASSERT_OK(uv_loop_close(&loop));
78e66f31c5Sopenharmony_ci}
79e66f31c5Sopenharmony_ci
80e66f31c5Sopenharmony_ci
81e66f31c5Sopenharmony_cistatic void assert_wait_child(pid_t child_pid) {
82e66f31c5Sopenharmony_ci  pid_t waited_pid;
83e66f31c5Sopenharmony_ci  int child_stat;
84e66f31c5Sopenharmony_ci
85e66f31c5Sopenharmony_ci  waited_pid = waitpid(child_pid, &child_stat, 0);
86e66f31c5Sopenharmony_ci  printf("Waited pid is %d with status %d\n", waited_pid, child_stat);
87e66f31c5Sopenharmony_ci  if (waited_pid == -1) {
88e66f31c5Sopenharmony_ci    perror("Failed to wait");
89e66f31c5Sopenharmony_ci  }
90e66f31c5Sopenharmony_ci  ASSERT_EQ(child_pid, waited_pid);
91e66f31c5Sopenharmony_ci  ASSERT(WIFEXITED(child_stat)); /* Clean exit, not a signal. */
92e66f31c5Sopenharmony_ci  ASSERT(!WIFSIGNALED(child_stat));
93e66f31c5Sopenharmony_ci  ASSERT_OK(WEXITSTATUS(child_stat));
94e66f31c5Sopenharmony_ci}
95e66f31c5Sopenharmony_ci
96e66f31c5Sopenharmony_ci
97e66f31c5Sopenharmony_ciTEST_IMPL(fork_timer) {
98e66f31c5Sopenharmony_ci  /* Timers continue to work after we fork. */
99e66f31c5Sopenharmony_ci
100e66f31c5Sopenharmony_ci  /*
101e66f31c5Sopenharmony_ci   * Establish the loop before we fork to make sure that it
102e66f31c5Sopenharmony_ci   * has state to get reset after the fork.
103e66f31c5Sopenharmony_ci   */
104e66f31c5Sopenharmony_ci  pid_t child_pid;
105e66f31c5Sopenharmony_ci
106e66f31c5Sopenharmony_ci  run_timer_loop_once();
107e66f31c5Sopenharmony_ci#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
108e66f31c5Sopenharmony_ci  child_pid = -1;
109e66f31c5Sopenharmony_ci#else
110e66f31c5Sopenharmony_ci  child_pid = fork();
111e66f31c5Sopenharmony_ci#endif
112e66f31c5Sopenharmony_ci  ASSERT_NE(child_pid, -1);
113e66f31c5Sopenharmony_ci
114e66f31c5Sopenharmony_ci  if (child_pid != 0) {
115e66f31c5Sopenharmony_ci    /* parent */
116e66f31c5Sopenharmony_ci    assert_wait_child(child_pid);
117e66f31c5Sopenharmony_ci  } else {
118e66f31c5Sopenharmony_ci    /* child */
119e66f31c5Sopenharmony_ci    ASSERT_OK(uv_loop_fork(uv_default_loop()));
120e66f31c5Sopenharmony_ci    run_timer_loop_once();
121e66f31c5Sopenharmony_ci  }
122e66f31c5Sopenharmony_ci
123e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(uv_default_loop());
124e66f31c5Sopenharmony_ci  return 0;
125e66f31c5Sopenharmony_ci}
126e66f31c5Sopenharmony_ci
127e66f31c5Sopenharmony_ci
128e66f31c5Sopenharmony_ciTEST_IMPL(fork_socketpair) {
129e66f31c5Sopenharmony_ci  /* A socket opened in the parent and accept'd in the
130e66f31c5Sopenharmony_ci     child works after a fork. */
131e66f31c5Sopenharmony_ci  pid_t child_pid;
132e66f31c5Sopenharmony_ci  int socket_fds[2];
133e66f31c5Sopenharmony_ci  uv_poll_t poll_handle;
134e66f31c5Sopenharmony_ci
135e66f31c5Sopenharmony_ci  /* Prime the loop. */
136e66f31c5Sopenharmony_ci  run_timer_loop_once();
137e66f31c5Sopenharmony_ci
138e66f31c5Sopenharmony_ci  ASSERT_OK(socketpair(AF_UNIX, SOCK_STREAM, 0, socket_fds));
139e66f31c5Sopenharmony_ci
140e66f31c5Sopenharmony_ci  /* Create the server watcher in the parent, use it in the child. */
141e66f31c5Sopenharmony_ci  ASSERT_OK(uv_poll_init(uv_default_loop(), &poll_handle, socket_fds[0]));
142e66f31c5Sopenharmony_ci
143e66f31c5Sopenharmony_ci#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
144e66f31c5Sopenharmony_ci  child_pid = -1;
145e66f31c5Sopenharmony_ci#else
146e66f31c5Sopenharmony_ci  child_pid = fork();
147e66f31c5Sopenharmony_ci#endif
148e66f31c5Sopenharmony_ci  ASSERT_NE(child_pid, -1);
149e66f31c5Sopenharmony_ci
150e66f31c5Sopenharmony_ci  if (child_pid != 0) {
151e66f31c5Sopenharmony_ci    /* parent */
152e66f31c5Sopenharmony_ci    ASSERT_EQ(3, send(socket_fds[1], "hi\n", 3, 0));
153e66f31c5Sopenharmony_ci    assert_wait_child(child_pid);
154e66f31c5Sopenharmony_ci  } else {
155e66f31c5Sopenharmony_ci    /* child */
156e66f31c5Sopenharmony_ci    ASSERT_OK(uv_loop_fork(uv_default_loop()));
157e66f31c5Sopenharmony_ci    ASSERT_OK(socket_cb_called);
158e66f31c5Sopenharmony_ci    ASSERT_OK(uv_poll_start(&poll_handle, UV_READABLE, socket_cb));
159e66f31c5Sopenharmony_ci    printf("Going to run the loop in the child\n");
160e66f31c5Sopenharmony_ci    ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
161e66f31c5Sopenharmony_ci    ASSERT_EQ(1, socket_cb_called);
162e66f31c5Sopenharmony_ci  }
163e66f31c5Sopenharmony_ci
164e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(uv_default_loop());
165e66f31c5Sopenharmony_ci  return 0;
166e66f31c5Sopenharmony_ci}
167e66f31c5Sopenharmony_ci
168e66f31c5Sopenharmony_ci
169e66f31c5Sopenharmony_ciTEST_IMPL(fork_socketpair_started) {
170e66f31c5Sopenharmony_ci  /* A socket opened in the parent and accept'd in the
171e66f31c5Sopenharmony_ci     child works after a fork, even if the watcher was already
172e66f31c5Sopenharmony_ci     started, and then stopped in the parent. */
173e66f31c5Sopenharmony_ci  pid_t child_pid;
174e66f31c5Sopenharmony_ci  int socket_fds[2];
175e66f31c5Sopenharmony_ci  int sync_pipe[2];
176e66f31c5Sopenharmony_ci  char sync_buf[1];
177e66f31c5Sopenharmony_ci  uv_poll_t poll_handle;
178e66f31c5Sopenharmony_ci
179e66f31c5Sopenharmony_ci  ASSERT_OK(pipe(sync_pipe));
180e66f31c5Sopenharmony_ci
181e66f31c5Sopenharmony_ci  /* Prime the loop. */
182e66f31c5Sopenharmony_ci  run_timer_loop_once();
183e66f31c5Sopenharmony_ci
184e66f31c5Sopenharmony_ci  ASSERT_OK(socketpair(AF_UNIX, SOCK_STREAM, 0, socket_fds));
185e66f31c5Sopenharmony_ci
186e66f31c5Sopenharmony_ci  /* Create and start the server watcher in the parent, use it in the child. */
187e66f31c5Sopenharmony_ci  ASSERT_OK(uv_poll_init(uv_default_loop(), &poll_handle, socket_fds[0]));
188e66f31c5Sopenharmony_ci  ASSERT_OK(uv_poll_start(&poll_handle, UV_READABLE, socket_cb));
189e66f31c5Sopenharmony_ci
190e66f31c5Sopenharmony_ci  /* Run the loop AFTER the poll watcher is registered to make sure it
191e66f31c5Sopenharmony_ci     gets passed to the kernel. Use NOWAIT and expect a non-zero
192e66f31c5Sopenharmony_ci     return to prove the poll watcher is active.
193e66f31c5Sopenharmony_ci  */
194e66f31c5Sopenharmony_ci  ASSERT_EQ(1, uv_run(uv_default_loop(), UV_RUN_NOWAIT));
195e66f31c5Sopenharmony_ci
196e66f31c5Sopenharmony_ci#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
197e66f31c5Sopenharmony_ci  child_pid = -1;
198e66f31c5Sopenharmony_ci#else
199e66f31c5Sopenharmony_ci  child_pid = fork();
200e66f31c5Sopenharmony_ci#endif
201e66f31c5Sopenharmony_ci  ASSERT_NE(child_pid, -1);
202e66f31c5Sopenharmony_ci
203e66f31c5Sopenharmony_ci  if (child_pid != 0) {
204e66f31c5Sopenharmony_ci    /* parent */
205e66f31c5Sopenharmony_ci    ASSERT_OK(uv_poll_stop(&poll_handle));
206e66f31c5Sopenharmony_ci    uv_close((uv_handle_t*)&poll_handle, NULL);
207e66f31c5Sopenharmony_ci    ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
208e66f31c5Sopenharmony_ci    ASSERT_OK(socket_cb_called);
209e66f31c5Sopenharmony_ci    ASSERT_EQ(1, write(sync_pipe[1], "1", 1)); /* alert child */
210e66f31c5Sopenharmony_ci    ASSERT_EQ(3, send(socket_fds[1], "hi\n", 3, 0));
211e66f31c5Sopenharmony_ci
212e66f31c5Sopenharmony_ci    ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
213e66f31c5Sopenharmony_ci    ASSERT_OK(socket_cb_called);
214e66f31c5Sopenharmony_ci
215e66f31c5Sopenharmony_ci    assert_wait_child(child_pid);
216e66f31c5Sopenharmony_ci  } else {
217e66f31c5Sopenharmony_ci    /* child */
218e66f31c5Sopenharmony_ci    printf("Child is %d\n", getpid());
219e66f31c5Sopenharmony_ci    ASSERT_EQ(1, read(sync_pipe[0], sync_buf, 1)); /* wait for parent */
220e66f31c5Sopenharmony_ci    ASSERT_OK(uv_loop_fork(uv_default_loop()));
221e66f31c5Sopenharmony_ci    ASSERT_OK(socket_cb_called);
222e66f31c5Sopenharmony_ci
223e66f31c5Sopenharmony_ci    printf("Going to run the loop in the child\n");
224e66f31c5Sopenharmony_ci    socket_cb_read_fd = socket_fds[0];
225e66f31c5Sopenharmony_ci    socket_cb_read_size = 3;
226e66f31c5Sopenharmony_ci    ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
227e66f31c5Sopenharmony_ci    ASSERT_EQ(1, socket_cb_called);
228e66f31c5Sopenharmony_ci    printf("Buf %s\n", socket_cb_read_buf);
229e66f31c5Sopenharmony_ci    ASSERT_OK(strcmp("hi\n", socket_cb_read_buf));
230e66f31c5Sopenharmony_ci  }
231e66f31c5Sopenharmony_ci
232e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(uv_default_loop());
233e66f31c5Sopenharmony_ci  return 0;
234e66f31c5Sopenharmony_ci}
235e66f31c5Sopenharmony_ci
236e66f31c5Sopenharmony_ci
237e66f31c5Sopenharmony_cistatic int fork_signal_cb_called;
238e66f31c5Sopenharmony_ci
239e66f31c5Sopenharmony_civoid fork_signal_to_child_cb(uv_signal_t* handle, int signum)
240e66f31c5Sopenharmony_ci{
241e66f31c5Sopenharmony_ci  fork_signal_cb_called = signum;
242e66f31c5Sopenharmony_ci  uv_close((uv_handle_t*)handle, NULL);
243e66f31c5Sopenharmony_ci}
244e66f31c5Sopenharmony_ci
245e66f31c5Sopenharmony_ci
246e66f31c5Sopenharmony_ciTEST_IMPL(fork_signal_to_child) {
247e66f31c5Sopenharmony_ci  /* A signal handler installed before forking
248e66f31c5Sopenharmony_ci     is run only in the child when the child is signalled. */
249e66f31c5Sopenharmony_ci  uv_signal_t signal_handle;
250e66f31c5Sopenharmony_ci  pid_t child_pid;
251e66f31c5Sopenharmony_ci  int sync_pipe[2];
252e66f31c5Sopenharmony_ci  char sync_buf[1];
253e66f31c5Sopenharmony_ci
254e66f31c5Sopenharmony_ci  fork_signal_cb_called = 0;    /* reset */
255e66f31c5Sopenharmony_ci
256e66f31c5Sopenharmony_ci  ASSERT_OK(pipe(sync_pipe));
257e66f31c5Sopenharmony_ci
258e66f31c5Sopenharmony_ci  /* Prime the loop. */
259e66f31c5Sopenharmony_ci  run_timer_loop_once();
260e66f31c5Sopenharmony_ci
261e66f31c5Sopenharmony_ci  ASSERT_OK(uv_signal_init(uv_default_loop(), &signal_handle));
262e66f31c5Sopenharmony_ci  ASSERT_OK(uv_signal_start(&signal_handle,
263e66f31c5Sopenharmony_ci                            fork_signal_to_child_cb,
264e66f31c5Sopenharmony_ci                            SIGUSR1));
265e66f31c5Sopenharmony_ci
266e66f31c5Sopenharmony_ci#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
267e66f31c5Sopenharmony_ci  child_pid = -1;
268e66f31c5Sopenharmony_ci#else
269e66f31c5Sopenharmony_ci  child_pid = fork();
270e66f31c5Sopenharmony_ci#endif
271e66f31c5Sopenharmony_ci  ASSERT_NE(child_pid, -1);
272e66f31c5Sopenharmony_ci
273e66f31c5Sopenharmony_ci  if (child_pid != 0) {
274e66f31c5Sopenharmony_ci    /* parent */
275e66f31c5Sopenharmony_ci    ASSERT_EQ(1, read(sync_pipe[0], sync_buf, 1)); /* wait for child */
276e66f31c5Sopenharmony_ci    ASSERT_OK(kill(child_pid, SIGUSR1));
277e66f31c5Sopenharmony_ci    /* Run the loop, make sure we don't get the signal. */
278e66f31c5Sopenharmony_ci    printf("Running loop in parent\n");
279e66f31c5Sopenharmony_ci    uv_unref((uv_handle_t*)&signal_handle);
280e66f31c5Sopenharmony_ci    ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_NOWAIT));
281e66f31c5Sopenharmony_ci    ASSERT_OK(fork_signal_cb_called);
282e66f31c5Sopenharmony_ci    printf("Waiting for child in parent\n");
283e66f31c5Sopenharmony_ci    assert_wait_child(child_pid);
284e66f31c5Sopenharmony_ci  } else {
285e66f31c5Sopenharmony_ci    /* child */
286e66f31c5Sopenharmony_ci    ASSERT_OK(uv_loop_fork(uv_default_loop()));
287e66f31c5Sopenharmony_ci    ASSERT_EQ(1, write(sync_pipe[1], "1", 1)); /* alert parent */
288e66f31c5Sopenharmony_ci    /* Get the signal. */
289e66f31c5Sopenharmony_ci    ASSERT_NE(0, uv_loop_alive(uv_default_loop()));
290e66f31c5Sopenharmony_ci    printf("Running loop in child\n");
291e66f31c5Sopenharmony_ci    ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_ONCE));
292e66f31c5Sopenharmony_ci    ASSERT_EQ(SIGUSR1, fork_signal_cb_called);
293e66f31c5Sopenharmony_ci  }
294e66f31c5Sopenharmony_ci
295e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(uv_default_loop());
296e66f31c5Sopenharmony_ci  return 0;
297e66f31c5Sopenharmony_ci}
298e66f31c5Sopenharmony_ci
299e66f31c5Sopenharmony_ci
300e66f31c5Sopenharmony_ciTEST_IMPL(fork_signal_to_child_closed) {
301e66f31c5Sopenharmony_ci  /* A signal handler installed before forking
302e66f31c5Sopenharmony_ci     doesn't get received anywhere when the child is signalled,
303e66f31c5Sopenharmony_ci     but isnt running the loop. */
304e66f31c5Sopenharmony_ci  uv_signal_t signal_handle;
305e66f31c5Sopenharmony_ci  pid_t child_pid;
306e66f31c5Sopenharmony_ci  int sync_pipe[2];
307e66f31c5Sopenharmony_ci  int sync_pipe2[2];
308e66f31c5Sopenharmony_ci  char sync_buf[1];
309e66f31c5Sopenharmony_ci  int r;
310e66f31c5Sopenharmony_ci
311e66f31c5Sopenharmony_ci  fork_signal_cb_called = 0;    /* reset */
312e66f31c5Sopenharmony_ci
313e66f31c5Sopenharmony_ci  ASSERT_OK(pipe(sync_pipe));
314e66f31c5Sopenharmony_ci  ASSERT_OK(pipe(sync_pipe2));
315e66f31c5Sopenharmony_ci
316e66f31c5Sopenharmony_ci  /* Prime the loop. */
317e66f31c5Sopenharmony_ci  run_timer_loop_once();
318e66f31c5Sopenharmony_ci
319e66f31c5Sopenharmony_ci  ASSERT_OK(uv_signal_init(uv_default_loop(), &signal_handle));
320e66f31c5Sopenharmony_ci  ASSERT_OK(uv_signal_start(&signal_handle,
321e66f31c5Sopenharmony_ci                            fork_signal_to_child_cb,
322e66f31c5Sopenharmony_ci                            SIGUSR1));
323e66f31c5Sopenharmony_ci
324e66f31c5Sopenharmony_ci#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
325e66f31c5Sopenharmony_ci  child_pid = -1;
326e66f31c5Sopenharmony_ci#else
327e66f31c5Sopenharmony_ci  child_pid = fork();
328e66f31c5Sopenharmony_ci#endif
329e66f31c5Sopenharmony_ci  ASSERT_NE(child_pid, -1);
330e66f31c5Sopenharmony_ci
331e66f31c5Sopenharmony_ci  if (child_pid != 0) {
332e66f31c5Sopenharmony_ci    /* parent */
333e66f31c5Sopenharmony_ci    printf("Wating on child in parent\n");
334e66f31c5Sopenharmony_ci    ASSERT_EQ(1, read(sync_pipe[0], sync_buf, 1)); /* wait for child */
335e66f31c5Sopenharmony_ci    printf("Parent killing child\n");
336e66f31c5Sopenharmony_ci    ASSERT_OK(kill(child_pid, SIGUSR1));
337e66f31c5Sopenharmony_ci    /* Run the loop, make sure we don't get the signal. */
338e66f31c5Sopenharmony_ci    printf("Running loop in parent\n");
339e66f31c5Sopenharmony_ci    uv_unref((uv_handle_t*)&signal_handle); /* so the loop can exit;
340e66f31c5Sopenharmony_ci                                               we *shouldn't* get any signals */
341e66f31c5Sopenharmony_ci    run_timer_loop_once(); /* but while we share a pipe, we do, so
342e66f31c5Sopenharmony_ci                              have something active. */
343e66f31c5Sopenharmony_ci    ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_ONCE));
344e66f31c5Sopenharmony_ci    printf("Signal in parent %d\n", fork_signal_cb_called);
345e66f31c5Sopenharmony_ci    ASSERT_OK(fork_signal_cb_called);
346e66f31c5Sopenharmony_ci    ASSERT_EQ(1, write(sync_pipe2[1], "1", 1)); /* alert child */
347e66f31c5Sopenharmony_ci    printf("Waiting for child in parent\n");
348e66f31c5Sopenharmony_ci    assert_wait_child(child_pid);
349e66f31c5Sopenharmony_ci  } else {
350e66f31c5Sopenharmony_ci    /* Child. Our signal handler should still be installed. */
351e66f31c5Sopenharmony_ci    ASSERT_OK(uv_loop_fork(uv_default_loop()));
352e66f31c5Sopenharmony_ci    printf("Checking loop in child\n");
353e66f31c5Sopenharmony_ci    ASSERT_NE(0, uv_loop_alive(uv_default_loop()));
354e66f31c5Sopenharmony_ci    printf("Alerting parent in child\n");
355e66f31c5Sopenharmony_ci    ASSERT_EQ(1, write(sync_pipe[1], "1", 1)); /* alert parent */
356e66f31c5Sopenharmony_ci    /* Don't run the loop. Wait for the parent to call us */
357e66f31c5Sopenharmony_ci    printf("Waiting on parent in child\n");
358e66f31c5Sopenharmony_ci    /* Wait for parent. read may fail if the parent tripped an ASSERT
359e66f31c5Sopenharmony_ci       and exited, so this ASSERT is generous.
360e66f31c5Sopenharmony_ci    */
361e66f31c5Sopenharmony_ci    r = read(sync_pipe2[0], sync_buf, 1);
362e66f31c5Sopenharmony_ci    ASSERT(-1 <= r && r <= 1);
363e66f31c5Sopenharmony_ci    ASSERT_OK(fork_signal_cb_called);
364e66f31c5Sopenharmony_ci    printf("Exiting child \n");
365e66f31c5Sopenharmony_ci    /* Note that we're deliberately not running the loop
366e66f31c5Sopenharmony_ci     * in the child, and also not closing the loop's handles,
367e66f31c5Sopenharmony_ci     * so the child default loop can't be cleanly closed.
368e66f31c5Sopenharmony_ci     * We need to explicitly exit to avoid an automatic failure
369e66f31c5Sopenharmony_ci     * in that case.
370e66f31c5Sopenharmony_ci     */
371e66f31c5Sopenharmony_ci    exit(0);
372e66f31c5Sopenharmony_ci  }
373e66f31c5Sopenharmony_ci
374e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(uv_default_loop());
375e66f31c5Sopenharmony_ci  return 0;
376e66f31c5Sopenharmony_ci}
377e66f31c5Sopenharmony_ci
378e66f31c5Sopenharmony_cistatic void fork_signal_cb(uv_signal_t* h, int s) {
379e66f31c5Sopenharmony_ci  fork_signal_cb_called = s;
380e66f31c5Sopenharmony_ci}
381e66f31c5Sopenharmony_cistatic void empty_close_cb(uv_handle_t* h){}
382e66f31c5Sopenharmony_ci
383e66f31c5Sopenharmony_ciTEST_IMPL(fork_close_signal_in_child) {
384e66f31c5Sopenharmony_ci  uv_loop_t loop;
385e66f31c5Sopenharmony_ci  uv_signal_t signal_handle;
386e66f31c5Sopenharmony_ci  pid_t child_pid;
387e66f31c5Sopenharmony_ci
388e66f31c5Sopenharmony_ci  ASSERT_OK(uv_loop_init(&loop));
389e66f31c5Sopenharmony_ci  ASSERT_OK(uv_signal_init(&loop, &signal_handle));
390e66f31c5Sopenharmony_ci  ASSERT_OK(uv_signal_start(&signal_handle, &fork_signal_cb, SIGHUP));
391e66f31c5Sopenharmony_ci
392e66f31c5Sopenharmony_ci  ASSERT_OK(kill(getpid(), SIGHUP));
393e66f31c5Sopenharmony_ci  child_pid = fork();
394e66f31c5Sopenharmony_ci  ASSERT_NE(child_pid, -1);
395e66f31c5Sopenharmony_ci  ASSERT_OK(fork_signal_cb_called);
396e66f31c5Sopenharmony_ci
397e66f31c5Sopenharmony_ci  if (!child_pid) {
398e66f31c5Sopenharmony_ci    uv_loop_fork(&loop);
399e66f31c5Sopenharmony_ci    uv_close((uv_handle_t*)&signal_handle, &empty_close_cb);
400e66f31c5Sopenharmony_ci    uv_run(&loop, UV_RUN_DEFAULT);
401e66f31c5Sopenharmony_ci    /* Child doesn't receive the signal */
402e66f31c5Sopenharmony_ci    ASSERT_OK(fork_signal_cb_called);
403e66f31c5Sopenharmony_ci  } else {
404e66f31c5Sopenharmony_ci    /* Parent. Runing once to receive the signal */
405e66f31c5Sopenharmony_ci    uv_run(&loop, UV_RUN_ONCE);
406e66f31c5Sopenharmony_ci    ASSERT_EQ(SIGHUP, fork_signal_cb_called);
407e66f31c5Sopenharmony_ci
408e66f31c5Sopenharmony_ci    /* loop should stop after closing the only handle */
409e66f31c5Sopenharmony_ci    uv_close((uv_handle_t*)&signal_handle, &empty_close_cb);
410e66f31c5Sopenharmony_ci    ASSERT_OK(uv_run(&loop, UV_RUN_DEFAULT));
411e66f31c5Sopenharmony_ci
412e66f31c5Sopenharmony_ci    assert_wait_child(child_pid);
413e66f31c5Sopenharmony_ci  }
414e66f31c5Sopenharmony_ci
415e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(&loop);
416e66f31c5Sopenharmony_ci  return 0;
417e66f31c5Sopenharmony_ci}
418e66f31c5Sopenharmony_ci
419e66f31c5Sopenharmony_ci
420e66f31c5Sopenharmony_cistatic void create_file(const char* name) {
421e66f31c5Sopenharmony_ci  int r;
422e66f31c5Sopenharmony_ci  uv_file file;
423e66f31c5Sopenharmony_ci  uv_fs_t req;
424e66f31c5Sopenharmony_ci
425e66f31c5Sopenharmony_ci  r = uv_fs_open(NULL, &req, name, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL);
426e66f31c5Sopenharmony_ci  ASSERT_GE(r, 0);
427e66f31c5Sopenharmony_ci  file = r;
428e66f31c5Sopenharmony_ci  uv_fs_req_cleanup(&req);
429e66f31c5Sopenharmony_ci  r = uv_fs_close(NULL, &req, file, NULL);
430e66f31c5Sopenharmony_ci  ASSERT_OK(r);
431e66f31c5Sopenharmony_ci  uv_fs_req_cleanup(&req);
432e66f31c5Sopenharmony_ci}
433e66f31c5Sopenharmony_ci
434e66f31c5Sopenharmony_ci
435e66f31c5Sopenharmony_cistatic void touch_file(const char* name) {
436e66f31c5Sopenharmony_ci  int r;
437e66f31c5Sopenharmony_ci  uv_file file;
438e66f31c5Sopenharmony_ci  uv_fs_t req;
439e66f31c5Sopenharmony_ci  uv_buf_t buf;
440e66f31c5Sopenharmony_ci
441e66f31c5Sopenharmony_ci  r = uv_fs_open(NULL, &req, name, O_RDWR, 0, NULL);
442e66f31c5Sopenharmony_ci  ASSERT_GE(r, 0);
443e66f31c5Sopenharmony_ci  file = r;
444e66f31c5Sopenharmony_ci  uv_fs_req_cleanup(&req);
445e66f31c5Sopenharmony_ci
446e66f31c5Sopenharmony_ci  buf = uv_buf_init("foo", 4);
447e66f31c5Sopenharmony_ci  r = uv_fs_write(NULL, &req, file, &buf, 1, -1, NULL);
448e66f31c5Sopenharmony_ci  ASSERT_GE(r, 0);
449e66f31c5Sopenharmony_ci  uv_fs_req_cleanup(&req);
450e66f31c5Sopenharmony_ci
451e66f31c5Sopenharmony_ci  r = uv_fs_close(NULL, &req, file, NULL);
452e66f31c5Sopenharmony_ci  ASSERT_OK(r);
453e66f31c5Sopenharmony_ci  uv_fs_req_cleanup(&req);
454e66f31c5Sopenharmony_ci}
455e66f31c5Sopenharmony_ci
456e66f31c5Sopenharmony_ci
457e66f31c5Sopenharmony_cistatic int timer_cb_touch_called;
458e66f31c5Sopenharmony_ci
459e66f31c5Sopenharmony_cistatic void timer_cb_touch(uv_timer_t* timer) {
460e66f31c5Sopenharmony_ci  uv_close((uv_handle_t*)timer, NULL);
461e66f31c5Sopenharmony_ci  touch_file("watch_file");
462e66f31c5Sopenharmony_ci  timer_cb_touch_called++;
463e66f31c5Sopenharmony_ci}
464e66f31c5Sopenharmony_ci
465e66f31c5Sopenharmony_ci
466e66f31c5Sopenharmony_cistatic int fs_event_cb_called;
467e66f31c5Sopenharmony_ci
468e66f31c5Sopenharmony_cistatic void fs_event_cb_file_current_dir(uv_fs_event_t* handle,
469e66f31c5Sopenharmony_ci                                         const char* filename,
470e66f31c5Sopenharmony_ci                                         int events,
471e66f31c5Sopenharmony_ci                                         int status) {
472e66f31c5Sopenharmony_ci  ASSERT_OK(fs_event_cb_called);
473e66f31c5Sopenharmony_ci  ++fs_event_cb_called;
474e66f31c5Sopenharmony_ci  ASSERT_OK(status);
475e66f31c5Sopenharmony_ci#if defined(__APPLE__) || defined(__linux__)
476e66f31c5Sopenharmony_ci  ASSERT_OK(strcmp(filename, "watch_file"));
477e66f31c5Sopenharmony_ci#else
478e66f31c5Sopenharmony_ci  ASSERT(filename == NULL || strcmp(filename, "watch_file") == 0);
479e66f31c5Sopenharmony_ci#endif
480e66f31c5Sopenharmony_ci  uv_close((uv_handle_t*)handle, NULL);
481e66f31c5Sopenharmony_ci}
482e66f31c5Sopenharmony_ci
483e66f31c5Sopenharmony_ci
484e66f31c5Sopenharmony_cistatic void assert_watch_file_current_dir(uv_loop_t* const loop, int file_or_dir) {
485e66f31c5Sopenharmony_ci  uv_timer_t timer;
486e66f31c5Sopenharmony_ci  uv_fs_event_t fs_event;
487e66f31c5Sopenharmony_ci  int r;
488e66f31c5Sopenharmony_ci
489e66f31c5Sopenharmony_ci  /* Setup */
490e66f31c5Sopenharmony_ci  remove("watch_file");
491e66f31c5Sopenharmony_ci  create_file("watch_file");
492e66f31c5Sopenharmony_ci
493e66f31c5Sopenharmony_ci  r = uv_fs_event_init(loop, &fs_event);
494e66f31c5Sopenharmony_ci  ASSERT_OK(r);
495e66f31c5Sopenharmony_ci  /* watching a dir is the only way to get fsevents involved on apple
496e66f31c5Sopenharmony_ci     platforms */
497e66f31c5Sopenharmony_ci  r = uv_fs_event_start(&fs_event,
498e66f31c5Sopenharmony_ci                        fs_event_cb_file_current_dir,
499e66f31c5Sopenharmony_ci                        file_or_dir == 1 ? "." : "watch_file",
500e66f31c5Sopenharmony_ci                        0);
501e66f31c5Sopenharmony_ci  ASSERT_OK(r);
502e66f31c5Sopenharmony_ci
503e66f31c5Sopenharmony_ci  r = uv_timer_init(loop, &timer);
504e66f31c5Sopenharmony_ci  ASSERT_OK(r);
505e66f31c5Sopenharmony_ci
506e66f31c5Sopenharmony_ci  r = uv_timer_start(&timer, timer_cb_touch, 100, 0);
507e66f31c5Sopenharmony_ci  ASSERT_OK(r);
508e66f31c5Sopenharmony_ci
509e66f31c5Sopenharmony_ci  ASSERT_OK(timer_cb_touch_called);
510e66f31c5Sopenharmony_ci  ASSERT_OK(fs_event_cb_called);
511e66f31c5Sopenharmony_ci
512e66f31c5Sopenharmony_ci  uv_run(loop, UV_RUN_DEFAULT);
513e66f31c5Sopenharmony_ci
514e66f31c5Sopenharmony_ci  ASSERT_EQ(1, timer_cb_touch_called);
515e66f31c5Sopenharmony_ci  ASSERT_EQ(1, fs_event_cb_called);
516e66f31c5Sopenharmony_ci
517e66f31c5Sopenharmony_ci  /* Cleanup */
518e66f31c5Sopenharmony_ci  remove("watch_file");
519e66f31c5Sopenharmony_ci  fs_event_cb_called = 0;
520e66f31c5Sopenharmony_ci  timer_cb_touch_called = 0;
521e66f31c5Sopenharmony_ci  uv_run(loop, UV_RUN_DEFAULT); /* flush pending closes */
522e66f31c5Sopenharmony_ci}
523e66f31c5Sopenharmony_ci
524e66f31c5Sopenharmony_ci
525e66f31c5Sopenharmony_ci#define FS_TEST_FILE 0
526e66f31c5Sopenharmony_ci#define FS_TEST_DIR 1
527e66f31c5Sopenharmony_ci
528e66f31c5Sopenharmony_cistatic int _do_fork_fs_events_child(int file_or_dir) {
529e66f31c5Sopenharmony_ci  /* basic fsevents work in the child after a fork */
530e66f31c5Sopenharmony_ci  pid_t child_pid;
531e66f31c5Sopenharmony_ci  uv_loop_t loop;
532e66f31c5Sopenharmony_ci
533e66f31c5Sopenharmony_ci  /* Watch in the parent, prime the loop and/or threads. */
534e66f31c5Sopenharmony_ci  assert_watch_file_current_dir(uv_default_loop(), file_or_dir);
535e66f31c5Sopenharmony_ci#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
536e66f31c5Sopenharmony_ci  child_pid = -1;
537e66f31c5Sopenharmony_ci#else
538e66f31c5Sopenharmony_ci  child_pid = fork();
539e66f31c5Sopenharmony_ci#endif
540e66f31c5Sopenharmony_ci  ASSERT_NE(child_pid, -1);
541e66f31c5Sopenharmony_ci
542e66f31c5Sopenharmony_ci  if (child_pid != 0) {
543e66f31c5Sopenharmony_ci    /* parent */
544e66f31c5Sopenharmony_ci    assert_wait_child(child_pid);
545e66f31c5Sopenharmony_ci  } else {
546e66f31c5Sopenharmony_ci    /* child */
547e66f31c5Sopenharmony_ci    /* Ee can watch in a new loop, but dirs only work
548e66f31c5Sopenharmony_ci       if we're on linux. */
549e66f31c5Sopenharmony_ci#if defined(__APPLE__)
550e66f31c5Sopenharmony_ci    file_or_dir = FS_TEST_FILE;
551e66f31c5Sopenharmony_ci#endif
552e66f31c5Sopenharmony_ci    printf("Running child\n");
553e66f31c5Sopenharmony_ci    uv_loop_init(&loop);
554e66f31c5Sopenharmony_ci    printf("Child first watch\n");
555e66f31c5Sopenharmony_ci    assert_watch_file_current_dir(&loop, file_or_dir);
556e66f31c5Sopenharmony_ci    ASSERT_OK(uv_loop_close(&loop));
557e66f31c5Sopenharmony_ci    printf("Child second watch default loop\n");
558e66f31c5Sopenharmony_ci    /* Ee can watch in the default loop. */
559e66f31c5Sopenharmony_ci    ASSERT_OK(uv_loop_fork(uv_default_loop()));
560e66f31c5Sopenharmony_ci    /* On some platforms (OS X), if we don't update the time now,
561e66f31c5Sopenharmony_ci     * the timer cb fires before the event loop enters uv__io_poll,
562e66f31c5Sopenharmony_ci     * instead of after, meaning we don't see the change! This may be
563e66f31c5Sopenharmony_ci     * a general race.
564e66f31c5Sopenharmony_ci     */
565e66f31c5Sopenharmony_ci    uv_update_time(uv_default_loop());
566e66f31c5Sopenharmony_ci    assert_watch_file_current_dir(uv_default_loop(), file_or_dir);
567e66f31c5Sopenharmony_ci
568e66f31c5Sopenharmony_ci    /* We can close the parent loop successfully too. This is
569e66f31c5Sopenharmony_ci       especially important on Apple platforms where if we're not
570e66f31c5Sopenharmony_ci       careful trying to touch the CFRunLoop, even just to shut it
571e66f31c5Sopenharmony_ci       down, that we allocated in the FS_TEST_DIR case would crash. */
572e66f31c5Sopenharmony_ci    ASSERT_OK(uv_loop_close(uv_default_loop()));
573e66f31c5Sopenharmony_ci
574e66f31c5Sopenharmony_ci    printf("Exiting child \n");
575e66f31c5Sopenharmony_ci  }
576e66f31c5Sopenharmony_ci
577e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(uv_default_loop());
578e66f31c5Sopenharmony_ci  return 0;
579e66f31c5Sopenharmony_ci
580e66f31c5Sopenharmony_ci}
581e66f31c5Sopenharmony_ci
582e66f31c5Sopenharmony_ci
583e66f31c5Sopenharmony_ciTEST_IMPL(fork_fs_events_child) {
584e66f31c5Sopenharmony_ci#if defined(NO_FS_EVENTS)
585e66f31c5Sopenharmony_ci  RETURN_SKIP(NO_FS_EVENTS);
586e66f31c5Sopenharmony_ci#endif
587e66f31c5Sopenharmony_ci  return _do_fork_fs_events_child(FS_TEST_FILE);
588e66f31c5Sopenharmony_ci}
589e66f31c5Sopenharmony_ci
590e66f31c5Sopenharmony_ci
591e66f31c5Sopenharmony_ciTEST_IMPL(fork_fs_events_child_dir) {
592e66f31c5Sopenharmony_ci#if defined(NO_FS_EVENTS)
593e66f31c5Sopenharmony_ci  RETURN_SKIP(NO_FS_EVENTS);
594e66f31c5Sopenharmony_ci#endif
595e66f31c5Sopenharmony_ci#if defined(__APPLE__) || defined (__linux__)
596e66f31c5Sopenharmony_ci  return _do_fork_fs_events_child(FS_TEST_DIR);
597e66f31c5Sopenharmony_ci#else
598e66f31c5Sopenharmony_ci  /* You can't spin up a cfrunloop thread on an apple platform
599e66f31c5Sopenharmony_ci     and then fork. See
600e66f31c5Sopenharmony_ci     http://objectivistc.tumblr.com/post/16187948939/you-must-exec-a-core-foundation-fork-safety-tale
601e66f31c5Sopenharmony_ci  */
602e66f31c5Sopenharmony_ci  return 0;
603e66f31c5Sopenharmony_ci#endif
604e66f31c5Sopenharmony_ci}
605e66f31c5Sopenharmony_ci
606e66f31c5Sopenharmony_ci
607e66f31c5Sopenharmony_ciTEST_IMPL(fork_fs_events_file_parent_child) {
608e66f31c5Sopenharmony_ci#if defined(NO_FS_EVENTS)
609e66f31c5Sopenharmony_ci  RETURN_SKIP(NO_FS_EVENTS);
610e66f31c5Sopenharmony_ci#endif
611e66f31c5Sopenharmony_ci#if defined(__sun) || defined(_AIX) || defined(__MVS__)
612e66f31c5Sopenharmony_ci  /* It's not possible to implement this without additional
613e66f31c5Sopenharmony_ci   * bookkeeping on SunOS. For AIX it is possible, but has to be
614e66f31c5Sopenharmony_ci   * written. See https://github.com/libuv/libuv/pull/846#issuecomment-287170420
615e66f31c5Sopenharmony_ci   * TODO: On z/OS, we need to open another message queue and subscribe to the
616e66f31c5Sopenharmony_ci   * same events as the parent.
617e66f31c5Sopenharmony_ci   */
618e66f31c5Sopenharmony_ci  return 0;
619e66f31c5Sopenharmony_ci#else
620e66f31c5Sopenharmony_ci  /* Establishing a started fs events watcher in the parent should
621e66f31c5Sopenharmony_ci     still work in the child. */
622e66f31c5Sopenharmony_ci  uv_timer_t timer;
623e66f31c5Sopenharmony_ci  uv_fs_event_t fs_event;
624e66f31c5Sopenharmony_ci  int r;
625e66f31c5Sopenharmony_ci  pid_t child_pid;
626e66f31c5Sopenharmony_ci  uv_loop_t* loop;
627e66f31c5Sopenharmony_ci
628e66f31c5Sopenharmony_ci  loop = uv_default_loop();
629e66f31c5Sopenharmony_ci
630e66f31c5Sopenharmony_ci  /* Setup */
631e66f31c5Sopenharmony_ci  remove("watch_file");
632e66f31c5Sopenharmony_ci  create_file("watch_file");
633e66f31c5Sopenharmony_ci
634e66f31c5Sopenharmony_ci  r = uv_fs_event_init(loop, &fs_event);
635e66f31c5Sopenharmony_ci  ASSERT_OK(r);
636e66f31c5Sopenharmony_ci  r = uv_fs_event_start(&fs_event,
637e66f31c5Sopenharmony_ci                        fs_event_cb_file_current_dir,
638e66f31c5Sopenharmony_ci                        "watch_file",
639e66f31c5Sopenharmony_ci                        0);
640e66f31c5Sopenharmony_ci  ASSERT_OK(r);
641e66f31c5Sopenharmony_ci
642e66f31c5Sopenharmony_ci  r = uv_timer_init(loop, &timer);
643e66f31c5Sopenharmony_ci  ASSERT_OK(r);
644e66f31c5Sopenharmony_ci
645e66f31c5Sopenharmony_ci#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
646e66f31c5Sopenharmony_ci  child_pid = -1;
647e66f31c5Sopenharmony_ci#else
648e66f31c5Sopenharmony_ci  child_pid = fork();
649e66f31c5Sopenharmony_ci#endif
650e66f31c5Sopenharmony_ci  ASSERT_NE(child_pid, -1);
651e66f31c5Sopenharmony_ci  if (child_pid != 0) {
652e66f31c5Sopenharmony_ci    /* parent */
653e66f31c5Sopenharmony_ci    assert_wait_child(child_pid);
654e66f31c5Sopenharmony_ci  } else {
655e66f31c5Sopenharmony_ci    /* child */
656e66f31c5Sopenharmony_ci    printf("Running child\n");
657e66f31c5Sopenharmony_ci    ASSERT_OK(uv_loop_fork(loop));
658e66f31c5Sopenharmony_ci
659e66f31c5Sopenharmony_ci    r = uv_timer_start(&timer, timer_cb_touch, 100, 0);
660e66f31c5Sopenharmony_ci    ASSERT_OK(r);
661e66f31c5Sopenharmony_ci
662e66f31c5Sopenharmony_ci    ASSERT_OK(timer_cb_touch_called);
663e66f31c5Sopenharmony_ci    ASSERT_OK(fs_event_cb_called);
664e66f31c5Sopenharmony_ci    printf("Running loop in child \n");
665e66f31c5Sopenharmony_ci    uv_run(loop, UV_RUN_DEFAULT);
666e66f31c5Sopenharmony_ci
667e66f31c5Sopenharmony_ci    ASSERT_EQ(1, timer_cb_touch_called);
668e66f31c5Sopenharmony_ci    ASSERT_EQ(1, fs_event_cb_called);
669e66f31c5Sopenharmony_ci
670e66f31c5Sopenharmony_ci    /* Cleanup */
671e66f31c5Sopenharmony_ci    remove("watch_file");
672e66f31c5Sopenharmony_ci    fs_event_cb_called = 0;
673e66f31c5Sopenharmony_ci    timer_cb_touch_called = 0;
674e66f31c5Sopenharmony_ci    uv_run(loop, UV_RUN_DEFAULT); /* Flush pending closes. */
675e66f31c5Sopenharmony_ci  }
676e66f31c5Sopenharmony_ci
677e66f31c5Sopenharmony_ci
678e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(loop);
679e66f31c5Sopenharmony_ci  return 0;
680e66f31c5Sopenharmony_ci#endif
681e66f31c5Sopenharmony_ci}
682e66f31c5Sopenharmony_ci
683e66f31c5Sopenharmony_ci
684e66f31c5Sopenharmony_cistatic int work_cb_count;
685e66f31c5Sopenharmony_cistatic int after_work_cb_count;
686e66f31c5Sopenharmony_ci
687e66f31c5Sopenharmony_ci
688e66f31c5Sopenharmony_cistatic void work_cb(uv_work_t* req) {
689e66f31c5Sopenharmony_ci  work_cb_count++;
690e66f31c5Sopenharmony_ci}
691e66f31c5Sopenharmony_ci
692e66f31c5Sopenharmony_ci
693e66f31c5Sopenharmony_cistatic void after_work_cb(uv_work_t* req, int status) {
694e66f31c5Sopenharmony_ci  ASSERT_OK(status);
695e66f31c5Sopenharmony_ci  after_work_cb_count++;
696e66f31c5Sopenharmony_ci}
697e66f31c5Sopenharmony_ci
698e66f31c5Sopenharmony_ci
699e66f31c5Sopenharmony_cistatic void assert_run_work(uv_loop_t* const loop) {
700e66f31c5Sopenharmony_ci  uv_work_t work_req;
701e66f31c5Sopenharmony_ci  int r;
702e66f31c5Sopenharmony_ci
703e66f31c5Sopenharmony_ci  ASSERT_OK(work_cb_count);
704e66f31c5Sopenharmony_ci  ASSERT_OK(after_work_cb_count);
705e66f31c5Sopenharmony_ci  printf("Queue in %d\n", getpid());
706e66f31c5Sopenharmony_ci  r = uv_queue_work(loop, &work_req, work_cb, after_work_cb);
707e66f31c5Sopenharmony_ci  ASSERT_OK(r);
708e66f31c5Sopenharmony_ci  printf("Running in %d\n", getpid());
709e66f31c5Sopenharmony_ci  uv_run(loop, UV_RUN_DEFAULT);
710e66f31c5Sopenharmony_ci
711e66f31c5Sopenharmony_ci  ASSERT_EQ(1, work_cb_count);
712e66f31c5Sopenharmony_ci  ASSERT_EQ(1, after_work_cb_count);
713e66f31c5Sopenharmony_ci
714e66f31c5Sopenharmony_ci  /* cleanup  */
715e66f31c5Sopenharmony_ci  work_cb_count = 0;
716e66f31c5Sopenharmony_ci  after_work_cb_count = 0;
717e66f31c5Sopenharmony_ci}
718e66f31c5Sopenharmony_ci
719e66f31c5Sopenharmony_ci
720e66f31c5Sopenharmony_ci#ifndef __MVS__
721e66f31c5Sopenharmony_ciTEST_IMPL(fork_threadpool_queue_work_simple) {
722e66f31c5Sopenharmony_ci  /* The threadpool works in a child process. */
723e66f31c5Sopenharmony_ci
724e66f31c5Sopenharmony_ci  pid_t child_pid;
725e66f31c5Sopenharmony_ci  uv_loop_t loop;
726e66f31c5Sopenharmony_ci
727e66f31c5Sopenharmony_ci#ifdef __TSAN__
728e66f31c5Sopenharmony_ci  RETURN_SKIP("ThreadSanitizer doesn't support multi-threaded fork");
729e66f31c5Sopenharmony_ci#endif
730e66f31c5Sopenharmony_ci
731e66f31c5Sopenharmony_ci  /* Prime the pool and default loop. */
732e66f31c5Sopenharmony_ci  assert_run_work(uv_default_loop());
733e66f31c5Sopenharmony_ci
734e66f31c5Sopenharmony_ci#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
735e66f31c5Sopenharmony_ci  child_pid = -1;
736e66f31c5Sopenharmony_ci#else
737e66f31c5Sopenharmony_ci  child_pid = fork();
738e66f31c5Sopenharmony_ci#endif
739e66f31c5Sopenharmony_ci  ASSERT_NE(child_pid, -1);
740e66f31c5Sopenharmony_ci
741e66f31c5Sopenharmony_ci  if (child_pid != 0) {
742e66f31c5Sopenharmony_ci    /* Parent. We can still run work. */
743e66f31c5Sopenharmony_ci    assert_run_work(uv_default_loop());
744e66f31c5Sopenharmony_ci    assert_wait_child(child_pid);
745e66f31c5Sopenharmony_ci  } else {
746e66f31c5Sopenharmony_ci    /* Child. We can work in a new loop. */
747e66f31c5Sopenharmony_ci    printf("Running child in %d\n", getpid());
748e66f31c5Sopenharmony_ci    uv_loop_init(&loop);
749e66f31c5Sopenharmony_ci    printf("Child first watch\n");
750e66f31c5Sopenharmony_ci    assert_run_work(&loop);
751e66f31c5Sopenharmony_ci    uv_loop_close(&loop);
752e66f31c5Sopenharmony_ci    printf("Child second watch default loop\n");
753e66f31c5Sopenharmony_ci    /* We can work in the default loop. */
754e66f31c5Sopenharmony_ci    ASSERT_OK(uv_loop_fork(uv_default_loop()));
755e66f31c5Sopenharmony_ci    assert_run_work(uv_default_loop());
756e66f31c5Sopenharmony_ci    printf("Exiting child \n");
757e66f31c5Sopenharmony_ci  }
758e66f31c5Sopenharmony_ci
759e66f31c5Sopenharmony_ci
760e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(uv_default_loop());
761e66f31c5Sopenharmony_ci  return 0;
762e66f31c5Sopenharmony_ci}
763e66f31c5Sopenharmony_ci#endif /* !__MVS__ */
764e66f31c5Sopenharmony_ci
765e66f31c5Sopenharmony_ci#else
766e66f31c5Sopenharmony_ci
767e66f31c5Sopenharmony_citypedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
768e66f31c5Sopenharmony_ci
769e66f31c5Sopenharmony_ci#endif /* !_WIN32 */
770