libuv-svace-build

Форк
0
/
test-fork.c 
769 строк · 20.6 Кб
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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.