xref: /libuv/test/test-fork.c (revision 011a1ac1)
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 
timer_cb(uv_timer_t * timer)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 
socket_cb(uv_poll_t * poll,int status,int events)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 
run_timer_loop_once(void)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 
assert_wait_child(pid_t child_pid)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 
TEST_IMPL(fork_timer)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 
TEST_IMPL(fork_socketpair)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 
TEST_IMPL(fork_socketpair_started)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 
fork_signal_to_child_cb(uv_signal_t * handle,int signum)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 
TEST_IMPL(fork_signal_to_child)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 
TEST_IMPL(fork_signal_to_child_closed)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 
fork_signal_cb(uv_signal_t * h,int s)378 static void fork_signal_cb(uv_signal_t* h, int s) {
379   fork_signal_cb_called = s;
380 }
empty_close_cb(uv_handle_t * h)381 static void empty_close_cb(uv_handle_t* h){}
382 
TEST_IMPL(fork_close_signal_in_child)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 
create_file(const char * name)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 
touch_file(const char * name)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 
timer_cb_touch(uv_timer_t * timer)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 
fs_event_cb_file_current_dir(uv_fs_event_t * handle,const char * filename,int events,int status)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 
assert_watch_file_current_dir(uv_loop_t * const loop,int file_or_dir)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 
_do_fork_fs_events_child(int file_or_dir)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 
TEST_IMPL(fork_fs_events_child)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 
TEST_IMPL(fork_fs_events_child_dir)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 
TEST_IMPL(fork_fs_events_file_parent_child)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 
work_cb(uv_work_t * req)688 static void work_cb(uv_work_t* req) {
689   work_cb_count++;
690 }
691 
692 
after_work_cb(uv_work_t * req,int status)693 static void after_work_cb(uv_work_t* req, int status) {
694   ASSERT_OK(status);
695   after_work_cb_count++;
696 }
697 
698 
assert_run_work(uv_loop_t * const loop)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__
TEST_IMPL(fork_threadpool_queue_work_simple)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