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