Alien-uv

 view release on metacpan or  search on metacpan

libuv/test/test-fork.c  view on Meta::CPAN

    printf("Going to run the loop in the child\n");
    socket_cb_read_fd = socket_fds[0];
    socket_cb_read_size = 3;
    ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
    ASSERT(1 == socket_cb_called);
    printf("Buf %s\n", socket_cb_read_buf);
    ASSERT(0 == strcmp("hi\n", socket_cb_read_buf));
  }

  MAKE_VALGRIND_HAPPY();
  return 0;
}


static int fork_signal_cb_called;

void fork_signal_to_child_cb(uv_signal_t* handle, int signum)
{
  fork_signal_cb_called = signum;
  uv_close((uv_handle_t*)handle, NULL);
}


TEST_IMPL(fork_signal_to_child) {
  /* A signal handler installed before forking
     is run only in the child when the child is signalled. */
  uv_signal_t signal_handle;
  pid_t child_pid;
  int sync_pipe[2];
  char sync_buf[1];

  fork_signal_cb_called = 0;    /* reset */

  ASSERT(0 == pipe(sync_pipe));

  /* Prime the loop. */
  run_timer_loop_once();

  ASSERT(0 == uv_signal_init(uv_default_loop(), &signal_handle));
  ASSERT(0 == uv_signal_start(&signal_handle, fork_signal_to_child_cb, SIGUSR1));

  child_pid = fork();
  ASSERT(child_pid != -1);

  if (child_pid != 0) {
    /* parent */
    ASSERT(1 == read(sync_pipe[0], sync_buf, 1)); /* wait for child */
    ASSERT(0 == kill(child_pid, SIGUSR1));
    /* Run the loop, make sure we don't get the signal. */
    printf("Running loop in parent\n");
    uv_unref((uv_handle_t*)&signal_handle);
    ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_NOWAIT));
    ASSERT(0 == fork_signal_cb_called);
    printf("Waiting for child in parent\n");
    assert_wait_child(child_pid);
  } else {
    /* child */
    ASSERT(0 == uv_loop_fork(uv_default_loop()));
    ASSERT(1 == write(sync_pipe[1], "1", 1)); /* alert parent */
    /* Get the signal. */
    ASSERT(0 != uv_loop_alive(uv_default_loop()));
    printf("Running loop in child\n");
    ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
    ASSERT(SIGUSR1 == fork_signal_cb_called);
  }

  MAKE_VALGRIND_HAPPY();
  return 0;
}


TEST_IMPL(fork_signal_to_child_closed) {
  /* A signal handler installed before forking
     doesn't get received anywhere when the child is signalled,
     but isnt running the loop. */
  uv_signal_t signal_handle;
  pid_t child_pid;
  int sync_pipe[2];
  int sync_pipe2[2];
  char sync_buf[1];
  int r;

  fork_signal_cb_called = 0;    /* reset */

  ASSERT(0 == pipe(sync_pipe));
  ASSERT(0 == pipe(sync_pipe2));

  /* Prime the loop. */
  run_timer_loop_once();

  ASSERT(0 == uv_signal_init(uv_default_loop(), &signal_handle));
  ASSERT(0 == uv_signal_start(&signal_handle, fork_signal_to_child_cb, SIGUSR1));

  child_pid = fork();
  ASSERT(child_pid != -1);

  if (child_pid != 0) {
    /* parent */
    printf("Wating on child in parent\n");
    ASSERT(1 == read(sync_pipe[0], sync_buf, 1)); /* wait for child */
    printf("Parent killing child\n");
    ASSERT(0 == kill(child_pid, SIGUSR1));
    /* Run the loop, make sure we don't get the signal. */
    printf("Running loop in parent\n");
    uv_unref((uv_handle_t*)&signal_handle); /* so the loop can exit;
                                               we *shouldn't* get any signals */
    run_timer_loop_once(); /* but while we share a pipe, we do, so
                              have something active. */
    ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
    printf("Signal in parent %d\n", fork_signal_cb_called);
    ASSERT(0 == fork_signal_cb_called);
    ASSERT(1 == write(sync_pipe2[1], "1", 1)); /* alert child */
    printf("Waiting for child in parent\n");
    assert_wait_child(child_pid);
  } else {
    /* Child. Our signal handler should still be installed. */
    ASSERT(0 == uv_loop_fork(uv_default_loop()));
    printf("Checking loop in child\n");
    ASSERT(0 != uv_loop_alive(uv_default_loop()));
    printf("Alerting parent in child\n");
    ASSERT(1 == write(sync_pipe[1], "1", 1)); /* alert parent */
    /* Don't run the loop. Wait for the parent to call us */
    printf("Waiting on parent in child\n");
    /* Wait for parent. read may fail if the parent tripped an ASSERT
       and exited, so this ASSERT is generous.
    */
    r = read(sync_pipe2[0], sync_buf, 1);
    ASSERT(-1 <= r && r <= 1);
    ASSERT(0 == fork_signal_cb_called);
    printf("Exiting child \n");
    /* Note that we're deliberately not running the loop
     * in the child, and also not closing the loop's handles,
     * so the child default loop can't be cleanly closed.
     * We need to explicitly exit to avoid an automatic failure
     * in that case.
     */
    exit(0);
  }

  MAKE_VALGRIND_HAPPY();
  return 0;
}


static void create_file(const char* name) {
  int r;
  uv_file file;
  uv_fs_t req;

  r = uv_fs_open(NULL, &req, name, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL);
  ASSERT(r >= 0);
  file = r;
  uv_fs_req_cleanup(&req);
  r = uv_fs_close(NULL, &req, file, NULL);
  ASSERT(r == 0);
  uv_fs_req_cleanup(&req);
}


static void touch_file(const char* name) {
  int r;
  uv_file file;
  uv_fs_t req;
  uv_buf_t buf;

  r = uv_fs_open(NULL, &req, name, O_RDWR, 0, NULL);
  ASSERT(r >= 0);
  file = r;
  uv_fs_req_cleanup(&req);

  buf = uv_buf_init("foo", 4);
  r = uv_fs_write(NULL, &req, file, &buf, 1, -1, NULL);
  ASSERT(r >= 0);
  uv_fs_req_cleanup(&req);

  r = uv_fs_close(NULL, &req, file, NULL);
  ASSERT(r == 0);
  uv_fs_req_cleanup(&req);
}



( run in 1.299 second using v1.01-cache-2.11-cpan-df04353d9ac )