From 758a76922beca511a4b086e45269896607df8a3c Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Mon, 13 Aug 2012 16:36:29 +0200 Subject: [PATCH] unix: fix SIGCHLD race in process.c Start the SIGCHLD signal watcher before calling fork(). There was a very subtle race where a child process could quit (and generate a SIGCHILD) before the signal handler was installed. To reproduce, call uv_spawn() repeatedly with the below x86_64 program: // compile with `gcc -O2 -nostdlib` void _start(void) { // syscall(SYS_exit, 0) __asm__ __volatile__ ( "xorq %rdi, %rdi;" "xorq %rax, %rax;" "mov $0x3c, %al;" "syscall;" ); for (;;); } --- src/unix/process.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/unix/process.c b/src/unix/process.c index 36ec40dd..e21e8ea0 100644 --- a/src/unix/process.c +++ b/src/unix/process.c @@ -400,6 +400,8 @@ int uv_spawn(uv_loop_t* loop, if (uv__make_pipe(signal_pipe, 0)) goto error; + uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD); + pid = fork(); if (pid == -1) { @@ -440,7 +442,6 @@ int uv_spawn(uv_loop_t* loop, q = uv__process_queue(loop, pid); ngx_queue_insert_tail(q, &process->queue); - uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD); process->pid = pid; process->exit_cb = options.exit_cb;