unix: remove dependency on ev_child
This commit is contained in:
parent
ee50db6e36
commit
75ba681913
@ -125,6 +125,7 @@ struct uv__io_s {
|
||||
uv_async_t uv_eio_done_poll_notifier; \
|
||||
uv_idle_t uv_eio_poller; \
|
||||
uv_handle_t* closing_handles; \
|
||||
ngx_queue_t process_handles[1]; \
|
||||
ngx_queue_t prepare_handles; \
|
||||
ngx_queue_t check_handles; \
|
||||
ngx_queue_t idle_handles; \
|
||||
@ -135,6 +136,7 @@ struct uv__io_s {
|
||||
struct uv__timers { struct uv_timer_s* rbh_root; } timer_handles; \
|
||||
uint64_t time; \
|
||||
void* signal_ctx; \
|
||||
uv_signal_t child_watcher; \
|
||||
UV_LOOP_PRIVATE_PLATFORM_FIELDS
|
||||
|
||||
#define UV_REQ_BUFSML_SIZE (4)
|
||||
@ -259,7 +261,7 @@ struct uv__io_s {
|
||||
int retcode;
|
||||
|
||||
#define UV_PROCESS_PRIVATE_FIELDS \
|
||||
ev_child child_watcher; \
|
||||
ngx_queue_t queue; \
|
||||
int errorno; \
|
||||
|
||||
#define UV_FS_PRIVATE_FIELDS \
|
||||
|
||||
@ -28,10 +28,13 @@
|
||||
|
||||
|
||||
int uv__loop_init(uv_loop_t* loop, int default_loop) {
|
||||
unsigned int i;
|
||||
int flags;
|
||||
|
||||
#if HAVE_KQUEUE
|
||||
int flags = EVBACKEND_KQUEUE;
|
||||
flags = EVBACKEND_KQUEUE;
|
||||
#else
|
||||
int flags = EVFLAG_AUTO;
|
||||
flags = EVFLAG_AUTO;
|
||||
#endif
|
||||
|
||||
memset(loop, 0, sizeof(*loop));
|
||||
@ -52,6 +55,13 @@ int uv__loop_init(uv_loop_t* loop, int default_loop) {
|
||||
ev_set_userdata(loop->ev, loop);
|
||||
eio_channel_init(&loop->uv_eio_channel, loop);
|
||||
|
||||
uv_signal_init(loop, &loop->child_watcher);
|
||||
uv__handle_unref(&loop->child_watcher);
|
||||
loop->child_watcher.flags |= UV__HANDLE_INTERNAL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(loop->process_handles); i++)
|
||||
ngx_queue_init(loop->process_handles + i);
|
||||
|
||||
#if __linux__
|
||||
loop->inotify_watchers = NULL;
|
||||
loop->inotify_fd = -1;
|
||||
|
||||
@ -22,13 +22,16 @@
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <TargetConditionals.h>
|
||||
@ -42,30 +45,71 @@ extern char **environ;
|
||||
#endif
|
||||
|
||||
|
||||
static void uv__chld(EV_P_ ev_child* watcher, int revents) {
|
||||
int status = watcher->rstatus;
|
||||
int exit_status = 0;
|
||||
int term_signal = 0;
|
||||
uv_process_t *process = watcher->data;
|
||||
static ngx_queue_t* uv__process_queue(uv_loop_t* loop, int pid) {
|
||||
assert(pid > 0);
|
||||
return loop->process_handles + pid % ARRAY_SIZE(loop->process_handles);
|
||||
}
|
||||
|
||||
assert(&process->child_watcher == watcher);
|
||||
assert(revents & EV_CHILD);
|
||||
|
||||
ev_child_stop(EV_A_ &process->child_watcher);
|
||||
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;
|
||||
|
||||
if (process->exit_cb == NULL)
|
||||
return;
|
||||
h = uv__process_queue(loop, pid);
|
||||
|
||||
if (WIFEXITED(status))
|
||||
exit_status = WEXITSTATUS(status);
|
||||
ngx_queue_foreach(q, h) {
|
||||
handle = ngx_queue_data(q, uv_process_t, queue);
|
||||
if (handle->pid == pid) return handle;
|
||||
}
|
||||
|
||||
if (WIFSIGNALED(status))
|
||||
term_signal = WTERMSIG(status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (process->errorno)
|
||||
uv__set_sys_error(process->loop, process->errorno);
|
||||
|
||||
process->exit_cb(process, exit_status, term_signal);
|
||||
static void uv__chld(uv_signal_t* handle, int signum) {
|
||||
uv_process_t* process;
|
||||
int exit_status;
|
||||
int term_signal;
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
assert(signum == SIGCHLD);
|
||||
|
||||
for (;;) {
|
||||
pid = waitpid(-1, &status, WNOHANG);
|
||||
|
||||
if (pid == 0)
|
||||
return;
|
||||
|
||||
if (pid == -1) {
|
||||
if (errno == ECHILD)
|
||||
return; /* XXX stop signal watcher? */
|
||||
else
|
||||
abort();
|
||||
}
|
||||
|
||||
process = uv__process_find(handle->loop, pid);
|
||||
if (process == NULL)
|
||||
continue; /* XXX bug? abort? */
|
||||
|
||||
if (process->exit_cb == NULL)
|
||||
continue;
|
||||
|
||||
exit_status = 0;
|
||||
term_signal = 0;
|
||||
|
||||
if (WIFEXITED(status))
|
||||
exit_status = WEXITSTATUS(status);
|
||||
|
||||
if (WIFSIGNALED(status))
|
||||
term_signal = WTERMSIG(status);
|
||||
|
||||
if (process->errorno)
|
||||
uv__set_sys_error(process->loop, process->errorno);
|
||||
|
||||
process->exit_cb(process, exit_status, term_signal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -306,6 +350,7 @@ int uv_spawn(uv_loop_t* loop,
|
||||
struct pollfd pfd;
|
||||
int (*pipes)[2];
|
||||
int stdio_count;
|
||||
ngx_queue_t* q;
|
||||
pid_t pid;
|
||||
int i;
|
||||
int r;
|
||||
@ -318,6 +363,7 @@ int uv_spawn(uv_loop_t* loop,
|
||||
|
||||
uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
|
||||
loop->counters.process_init++;
|
||||
ngx_queue_init(&process->queue);
|
||||
|
||||
stdio_count = options.stdio_count;
|
||||
if (stdio_count < 3)
|
||||
@ -402,12 +448,6 @@ int uv_spawn(uv_loop_t* loop,
|
||||
|
||||
close(signal_pipe[0]);
|
||||
|
||||
ev_child_init(&process->child_watcher, uv__chld, pid, 0);
|
||||
ev_child_start(process->loop->ev, &process->child_watcher);
|
||||
process->child_watcher.data = process;
|
||||
process->exit_cb = options.exit_cb;
|
||||
process->pid = pid;
|
||||
|
||||
for (i = 0; i < options.stdio_count; i++) {
|
||||
if (uv__process_open_stream(options.stdio + i, pipes[i], i == 0)) {
|
||||
while (i--) uv__process_close_stream(options.stdio + i);
|
||||
@ -415,9 +455,15 @@ int uv_spawn(uv_loop_t* loop,
|
||||
}
|
||||
}
|
||||
|
||||
uv__handle_start(process);
|
||||
free(pipes);
|
||||
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;
|
||||
uv__handle_start(process);
|
||||
|
||||
free(pipes);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
@ -457,6 +503,7 @@ uv_err_t uv_kill(int pid, int signum) {
|
||||
|
||||
|
||||
void uv__process_close(uv_process_t* handle) {
|
||||
ev_child_stop(handle->loop->ev, &handle->child_watcher);
|
||||
/* TODO stop signal watcher when this is the last handle */
|
||||
ngx_queue_remove(&handle->queue);
|
||||
uv__handle_stop(handle);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user