Skip to content

Commit

Permalink
unix: fix SIGCHLD processing in process.c
Browse files Browse the repository at this point in the history
Quick for for joyent#887.
  • Loading branch information
bnoordhuis authored and alexcrichton committed Aug 26, 2013
1 parent dfae9c3 commit 6415a4d
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 41 deletions.
1 change: 1 addition & 0 deletions include/uv-private/uv-unix.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ typedef struct {
#define UV_PROCESS_PRIVATE_FIELDS \
ngx_queue_t queue; \
int errorno; \
int status; \

#define UV_FS_PRIVATE_FIELDS \
const char *new_path; \
Expand Down
90 changes: 49 additions & 41 deletions src/unix/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,66 +47,73 @@ static ngx_queue_t* uv__process_queue(uv_loop_t* loop, int pid) {
}


static uv_process_t* uv__process_find(uv_loop_t* loop, int pid) {
uv_process_t* handle;
ngx_queue_t* h;
ngx_queue_t* q;

h = uv__process_queue(loop, pid);

ngx_queue_foreach(q, h) {
handle = ngx_queue_data(q, uv_process_t, queue);
if (handle->pid == pid) return handle;
}

return NULL;
}


static void uv__chld(uv_signal_t* handle, int signum) {
uv_process_t* process;
uv_loop_t* loop;
int exit_status;
int term_signal;
unsigned int i;
int status;
pid_t pid;
ngx_queue_t pending;
ngx_queue_t* h;
ngx_queue_t* q;

assert(signum == SIGCHLD);

for (;;) {
pid = waitpid(-1, &status, WNOHANG);
ngx_queue_init(&pending);
loop = handle->loop;

for (i = 0; i < ARRAY_SIZE(loop->process_handles); i++) {
h = loop->process_handles + i;
q = ngx_queue_head(h);

while (q != h) {
process = ngx_queue_data(q, uv_process_t, queue);
q = ngx_queue_next(q);

if (pid == 0)
return;
do
pid = waitpid(process->pid, &status, WNOHANG);
while (pid == -1 && errno == EINTR);

if (pid == -1) {
if (errno == ECHILD)
return; /* XXX stop signal watcher? */
else
abort();
if (pid == 0)
continue;

if (pid == -1) {
if (errno != ECHILD)
abort();
continue;
}

process->status = status;
ngx_queue_remove(&process->queue);
ngx_queue_insert_tail(&pending, &process->queue);
}

process = uv__process_find(handle->loop, pid);
if (process == NULL)
continue; /* XXX bug? abort? */
while (!ngx_queue_empty(&pending)) {
q = ngx_queue_head(&pending);
ngx_queue_remove(q);
ngx_queue_init(q);

if (process->exit_cb == NULL)
continue;
process = ngx_queue_data(q, uv_process_t, queue);
uv__handle_stop(process);

exit_status = 0;
term_signal = 0;
if (process->exit_cb == NULL)
continue;

if (WIFEXITED(status))
exit_status = WEXITSTATUS(status);
exit_status = 0;
if (WIFEXITED(process->status))
exit_status = WEXITSTATUS(process->status);

if (WIFSIGNALED(status))
term_signal = WTERMSIG(status);
term_signal = 0;
if (WIFSIGNALED(process->status))
term_signal = WTERMSIG(process->status);

if (process->errorno) {
uv__set_sys_error(process->loop, process->errorno);
exit_status = -1; /* execve() failed */
}
if (process->errorno != 0)
exit_status = process->errorno; /* execve() failed */

process->exit_cb(process, exit_status, term_signal);
process->exit_cb(process, exit_status, term_signal);
}
}
}

Expand Down Expand Up @@ -423,6 +430,7 @@ int uv_spawn(uv_loop_t* loop,

close(signal_pipe[1]);

process->status = 0;
process->errorno = 0;
do
r = read(signal_pipe[0], &process->errorno, sizeof(process->errorno));
Expand Down

0 comments on commit 6415a4d

Please sign in to comment.