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 )