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