uv: upgrade to 87dbffbd
This commit is contained in:
parent
b337577cf1
commit
30a0e58d63
2
deps/uv/include/uv-private/ev.h
vendored
2
deps/uv/include/uv-private/ev.h
vendored
@ -623,7 +623,7 @@ enum {
|
||||
};
|
||||
|
||||
#if EV_PROTOTYPES
|
||||
void ev_run (EV_P_ int flags EV_CPP (= 0));
|
||||
void ev_run (EV_P_ ev_tstamp waittime);
|
||||
void ev_break (EV_P_ int how EV_CPP (= EVBREAK_ONE)); /* break out of the loop */
|
||||
|
||||
/*
|
||||
|
45
deps/uv/include/uv-private/uv-unix.h
vendored
45
deps/uv/include/uv-private/uv-unix.h
vendored
@ -98,18 +98,21 @@ struct uv__io_s {
|
||||
# define UV_LOOP_PRIVATE_PLATFORM_FIELDS
|
||||
#endif
|
||||
|
||||
#define UV_LOOP_PRIVATE_FIELDS \
|
||||
/* Poll result queue */ \
|
||||
eio_channel uv_eio_channel; \
|
||||
struct ev_loop* ev; \
|
||||
/* Various thing for libeio. */ \
|
||||
uv_async_t uv_eio_want_poll_notifier; \
|
||||
uv_async_t uv_eio_done_poll_notifier; \
|
||||
uv_idle_t uv_eio_poller; \
|
||||
uv_handle_t* pending_handles; \
|
||||
ngx_queue_t prepare_handles; \
|
||||
ngx_queue_t check_handles; \
|
||||
ngx_queue_t idle_handles; \
|
||||
#define UV_LOOP_PRIVATE_FIELDS \
|
||||
/* Poll result queue */ \
|
||||
eio_channel uv_eio_channel; \
|
||||
struct ev_loop* ev; \
|
||||
/* Various thing for libeio. */ \
|
||||
uv_async_t uv_eio_want_poll_notifier; \
|
||||
uv_async_t uv_eio_done_poll_notifier; \
|
||||
uv_idle_t uv_eio_poller; \
|
||||
uv_handle_t* closing_handles; \
|
||||
ngx_queue_t prepare_handles; \
|
||||
ngx_queue_t check_handles; \
|
||||
ngx_queue_t idle_handles; \
|
||||
/* RB_HEAD(uv__timers, uv_timer_s) */ \
|
||||
struct uv__timers { struct uv_timer_s* rbh_root; } timer_handles; \
|
||||
uint64_t time; \
|
||||
UV_LOOP_PRIVATE_PLATFORM_FIELDS
|
||||
|
||||
#define UV_REQ_BUFSML_SIZE (4)
|
||||
@ -144,7 +147,7 @@ struct uv__io_s {
|
||||
/* TODO: union or classes please! */
|
||||
#define UV_HANDLE_PRIVATE_FIELDS \
|
||||
int flags; \
|
||||
uv_handle_t* next_pending; \
|
||||
uv_handle_t* next_closing; \
|
||||
|
||||
|
||||
#define UV_STREAM_PRIVATE_FIELDS \
|
||||
@ -186,7 +189,7 @@ struct uv__io_s {
|
||||
uv__io_t io_watcher;
|
||||
|
||||
|
||||
/* UV_PREPARE */ \
|
||||
/* UV_PREPARE */
|
||||
#define UV_PREPARE_PRIVATE_FIELDS \
|
||||
uv_prepare_cb prepare_cb; \
|
||||
ngx_queue_t queue;
|
||||
@ -211,9 +214,17 @@ struct uv__io_s {
|
||||
|
||||
|
||||
/* UV_TIMER */
|
||||
#define UV_TIMER_PRIVATE_FIELDS \
|
||||
ev_timer timer_watcher; \
|
||||
uv_timer_cb timer_cb;
|
||||
#define UV_TIMER_PRIVATE_FIELDS \
|
||||
/* RB_ENTRY(uv_timer_s) node; */ \
|
||||
struct { \
|
||||
struct uv_timer_s* rbe_left; \
|
||||
struct uv_timer_s* rbe_right; \
|
||||
struct uv_timer_s* rbe_parent; \
|
||||
int rbe_color; \
|
||||
} tree_entry; \
|
||||
uv_timer_cb timer_cb; \
|
||||
uint64_t timeout; \
|
||||
uint64_t repeat;
|
||||
|
||||
#define UV_GETADDRINFO_PRIVATE_FIELDS \
|
||||
uv_getaddrinfo_cb cb; \
|
||||
|
2
deps/uv/include/uv-private/uv-win.h
vendored
2
deps/uv/include/uv-private/uv-win.h
vendored
@ -454,7 +454,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
|
||||
struct uv_process_close_s { \
|
||||
UV_REQ_FIELDS \
|
||||
} close_req; \
|
||||
HANDLE child_stdio[3]; \
|
||||
void* child_stdio_buffer; \
|
||||
int exit_signal; \
|
||||
DWORD spawn_errno; \
|
||||
HANDLE wait_handle; \
|
||||
|
47
deps/uv/include/uv.h
vendored
47
deps/uv/include/uv.h
vendored
@ -301,6 +301,7 @@ typedef void (*uv_exit_cb)(uv_process_t*, int exit_status, int term_signal);
|
||||
typedef void (*uv_fs_cb)(uv_fs_t* req);
|
||||
typedef void (*uv_work_cb)(uv_work_t* req);
|
||||
typedef void (*uv_after_work_cb)(uv_work_t* req);
|
||||
typedef void (*uv_walk_cb)(uv_handle_t* handle, void* arg);
|
||||
|
||||
/*
|
||||
* This will be called repeatedly after the uv_fs_event_t is initialized.
|
||||
@ -382,6 +383,7 @@ struct uv_shutdown_s {
|
||||
/* read-only */ \
|
||||
uv_handle_type type; \
|
||||
/* private */ \
|
||||
ngx_queue_t handle_queue; \
|
||||
UV_HANDLE_PRIVATE_FIELDS \
|
||||
|
||||
/* The abstract base class of all handles. */
|
||||
@ -407,6 +409,12 @@ UV_EXTERN size_t uv_req_size(uv_req_type type);
|
||||
*/
|
||||
UV_EXTERN int uv_is_active(const uv_handle_t* handle);
|
||||
|
||||
/*
|
||||
* Walk the list of open handles.
|
||||
*/
|
||||
UV_EXTERN void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg);
|
||||
|
||||
|
||||
/*
|
||||
* Request handle to be closed. close_cb will be called asynchronously after
|
||||
* this call. This MUST be called on each handle before memory is released.
|
||||
@ -1157,15 +1165,17 @@ UV_EXTERN void uv_freeaddrinfo(struct addrinfo* ai);
|
||||
|
||||
/* uv_spawn() options */
|
||||
typedef enum {
|
||||
UV_IGNORE = 0x00,
|
||||
UV_CREATE_PIPE = 0x01,
|
||||
/*
|
||||
* UV_READABLE_PIPE and UV_WRITABLE_PIPE flags are set from
|
||||
* the child process perspective.
|
||||
UV_IGNORE = 0x00,
|
||||
UV_CREATE_PIPE = 0x01,
|
||||
UV_INHERIT_FD = 0x02,
|
||||
UV_INHERIT_STREAM = 0x04,
|
||||
|
||||
/* When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE
|
||||
* determine the direction of flow, from the child process' perspective. Both
|
||||
* flags may be specified to create a duplex data stream.
|
||||
*/
|
||||
UV_READABLE_PIPE = 0x02,
|
||||
UV_WRITABLE_PIPE = 0x04,
|
||||
UV_RAW_FD = 0x08
|
||||
UV_READABLE_PIPE = 0x10,
|
||||
UV_WRITABLE_PIPE = 0x20
|
||||
} uv_stdio_flags;
|
||||
|
||||
typedef struct uv_stdio_container_s {
|
||||
@ -1211,10 +1221,16 @@ typedef struct uv_process_options_s {
|
||||
uv_gid_t gid;
|
||||
|
||||
/*
|
||||
* A container of stdio streams (stdin/stdout/stderr)
|
||||
* The `stdio` field points to an array of uv_stdio_container_t structs that
|
||||
* describe the file descriptors that will be made available to the child
|
||||
* process. The convention is that stdio[0] points to stdin, fd 1 is used for
|
||||
* stdout, and fd 2 is stderr.
|
||||
*
|
||||
* Note that on windows file descriptors greater than 2 are available to the
|
||||
* child process only if the child processes uses the MSVCRT runtime.
|
||||
*/
|
||||
uv_stdio_container_t* stdio;
|
||||
int stdio_count;
|
||||
uv_stdio_container_t* stdio;
|
||||
} uv_process_options_t;
|
||||
|
||||
/*
|
||||
@ -1238,7 +1254,15 @@ enum uv_process_flags {
|
||||
* converting the argument list into a command line string. This option is
|
||||
* only meaningful on Windows systems. On unix it is silently ignored.
|
||||
*/
|
||||
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2)
|
||||
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2),
|
||||
/*
|
||||
* Spawn the child process in a detached state - this will make it a process
|
||||
* group leader, and will effectively enable the child to keep running after
|
||||
* the parent exits. Note that the child process will still keep the
|
||||
* parent's event loop alive unless the parent process calls uv_unref() on
|
||||
* the child's process handle.
|
||||
*/
|
||||
UV_PROCESS_DETACHED = (1 << 3)
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1668,6 +1692,7 @@ struct uv_loop_s {
|
||||
uv_err_t last_err;
|
||||
/* Loop reference counting */
|
||||
unsigned int active_handles;
|
||||
ngx_queue_t handle_queue;
|
||||
ngx_queue_t active_reqs;
|
||||
/* User data - use this for whatever. */
|
||||
void* data;
|
||||
|
181
deps/uv/src/unix/core.c
vendored
181
deps/uv/src/unix/core.c
vendored
@ -59,8 +59,6 @@
|
||||
static uv_loop_t default_loop_struct;
|
||||
static uv_loop_t* default_loop_ptr;
|
||||
|
||||
static void uv__finish_close(uv_handle_t* handle);
|
||||
|
||||
|
||||
void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
|
||||
handle->close_cb = close_cb;
|
||||
@ -116,7 +114,72 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
|
||||
}
|
||||
|
||||
handle->flags |= UV_CLOSING;
|
||||
uv__make_pending(handle);
|
||||
|
||||
handle->next_closing = handle->loop->closing_handles;
|
||||
handle->loop->closing_handles = handle;
|
||||
}
|
||||
|
||||
|
||||
static void uv__finish_close(uv_handle_t* handle) {
|
||||
assert(!uv__is_active(handle));
|
||||
assert(handle->flags & UV_CLOSING);
|
||||
assert(!(handle->flags & UV_CLOSED));
|
||||
handle->flags |= UV_CLOSED;
|
||||
|
||||
switch (handle->type) {
|
||||
case UV_PREPARE:
|
||||
case UV_CHECK:
|
||||
case UV_IDLE:
|
||||
case UV_ASYNC:
|
||||
case UV_TIMER:
|
||||
case UV_PROCESS:
|
||||
break;
|
||||
|
||||
case UV_NAMED_PIPE:
|
||||
case UV_TCP:
|
||||
case UV_TTY:
|
||||
assert(!uv__io_active(&((uv_stream_t*)handle)->read_watcher));
|
||||
assert(!uv__io_active(&((uv_stream_t*)handle)->write_watcher));
|
||||
assert(((uv_stream_t*)handle)->fd == -1);
|
||||
uv__stream_destroy((uv_stream_t*)handle);
|
||||
break;
|
||||
|
||||
case UV_UDP:
|
||||
uv__udp_finish_close((uv_udp_t*)handle);
|
||||
break;
|
||||
|
||||
case UV_FS_EVENT:
|
||||
break;
|
||||
|
||||
case UV_POLL:
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
uv__handle_unref(handle);
|
||||
ngx_queue_remove(&handle->handle_queue);
|
||||
|
||||
if (handle->close_cb) {
|
||||
handle->close_cb(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void uv__run_closing_handles(uv_loop_t* loop) {
|
||||
uv_handle_t* p;
|
||||
uv_handle_t* q;
|
||||
|
||||
p = loop->closing_handles;
|
||||
loop->closing_handles = NULL;
|
||||
|
||||
while (p) {
|
||||
q = p->next_closing;
|
||||
uv__finish_close(p);
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -163,67 +226,44 @@ void uv_loop_delete(uv_loop_t* loop) {
|
||||
}
|
||||
|
||||
|
||||
static void uv__run_pending(uv_loop_t* loop) {
|
||||
uv_handle_t* p;
|
||||
uv_handle_t* q;
|
||||
|
||||
if (!loop->pending_handles)
|
||||
return;
|
||||
|
||||
for (p = loop->pending_handles, loop->pending_handles = NULL; p; p = q) {
|
||||
q = p->next_pending;
|
||||
p->next_pending = NULL;
|
||||
p->flags &= ~UV__PENDING;
|
||||
|
||||
if (p->flags & UV_CLOSING) {
|
||||
uv__finish_close(p);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (p->type) {
|
||||
case UV_NAMED_PIPE:
|
||||
case UV_TCP:
|
||||
case UV_TTY:
|
||||
uv__stream_pending((uv_stream_t*)p);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void uv__poll(uv_loop_t* loop, int block) {
|
||||
static void uv__poll(uv_loop_t* loop, unsigned int timeout) {
|
||||
/* bump the loop's refcount, otherwise libev does
|
||||
* a zero timeout poll and we end up busy looping
|
||||
*/
|
||||
ev_ref(loop->ev);
|
||||
ev_run(loop->ev, block ? EVRUN_ONCE : EVRUN_NOWAIT);
|
||||
ev_run(loop->ev, timeout / 1000.);
|
||||
ev_unref(loop->ev);
|
||||
}
|
||||
|
||||
|
||||
static int uv__should_block(uv_loop_t* loop) {
|
||||
return loop->active_handles && ngx_queue_empty(&loop->idle_handles);
|
||||
static unsigned int uv__poll_timeout(uv_loop_t* loop) {
|
||||
if (!uv__has_active_handles(loop))
|
||||
return 0;
|
||||
|
||||
if (!ngx_queue_empty(&loop->idle_handles))
|
||||
return 0;
|
||||
|
||||
return uv__next_timeout(loop);
|
||||
}
|
||||
|
||||
|
||||
static int uv__run(uv_loop_t* loop) {
|
||||
uv_update_time(loop);
|
||||
uv__run_timers(loop);
|
||||
uv__run_idle(loop);
|
||||
uv__run_pending(loop);
|
||||
|
||||
if (uv__has_active_handles(loop) || uv__has_active_reqs(loop)) {
|
||||
uv__run_prepare(loop);
|
||||
/* Need to poll even if there are no active handles left, otherwise
|
||||
* uv_work_t reqs won't complete...
|
||||
*/
|
||||
uv__poll(loop, uv__should_block(loop));
|
||||
uv__poll(loop, uv__poll_timeout(loop));
|
||||
uv__run_check(loop);
|
||||
}
|
||||
|
||||
return uv__has_pending_handles(loop)
|
||||
|| uv__has_active_handles(loop)
|
||||
|| uv__has_active_reqs(loop);
|
||||
uv__run_closing_handles(loop);
|
||||
|
||||
return uv__has_active_handles(loop) || uv__has_active_reqs(loop);
|
||||
}
|
||||
|
||||
|
||||
@ -244,66 +284,19 @@ void uv__handle_init(uv_loop_t* loop, uv_handle_t* handle,
|
||||
|
||||
handle->loop = loop;
|
||||
handle->type = type;
|
||||
handle->flags = UV__REF; /* ref the loop when active */
|
||||
handle->next_pending = NULL;
|
||||
}
|
||||
|
||||
|
||||
void uv__finish_close(uv_handle_t* handle) {
|
||||
assert(!uv__is_active(handle));
|
||||
assert(handle->flags & UV_CLOSING);
|
||||
assert(!(handle->flags & UV_CLOSED));
|
||||
handle->flags |= UV_CLOSED;
|
||||
|
||||
switch (handle->type) {
|
||||
case UV_PREPARE:
|
||||
case UV_CHECK:
|
||||
case UV_IDLE:
|
||||
case UV_ASYNC:
|
||||
case UV_TIMER:
|
||||
case UV_PROCESS:
|
||||
break;
|
||||
|
||||
case UV_NAMED_PIPE:
|
||||
case UV_TCP:
|
||||
case UV_TTY:
|
||||
assert(!uv__io_active(&((uv_stream_t*)handle)->read_watcher));
|
||||
assert(!uv__io_active(&((uv_stream_t*)handle)->write_watcher));
|
||||
assert(((uv_stream_t*)handle)->fd == -1);
|
||||
uv__stream_destroy((uv_stream_t*)handle);
|
||||
break;
|
||||
|
||||
case UV_UDP:
|
||||
uv__udp_finish_close((uv_udp_t*)handle);
|
||||
break;
|
||||
|
||||
case UV_FS_EVENT:
|
||||
break;
|
||||
|
||||
case UV_POLL:
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (handle->close_cb) {
|
||||
handle->close_cb(handle);
|
||||
}
|
||||
|
||||
uv__handle_unref(handle);
|
||||
handle->flags = UV__HANDLE_REF; /* ref the loop when active */
|
||||
handle->next_closing = NULL;
|
||||
ngx_queue_insert_tail(&loop->handle_queue, &handle->handle_queue);
|
||||
}
|
||||
|
||||
|
||||
void uv_update_time(uv_loop_t* loop) {
|
||||
ev_now_update(loop->ev);
|
||||
loop->time = uv_hrtime() / 1000000;
|
||||
}
|
||||
|
||||
|
||||
int64_t uv_now(uv_loop_t* loop) {
|
||||
return (int64_t)(ev_now(loop->ev) * 1000);
|
||||
return loop->time;
|
||||
}
|
||||
|
||||
|
||||
|
95
deps/uv/src/unix/ev/ev.c
vendored
95
deps/uv/src/unix/ev/ev.c
vendored
@ -2389,7 +2389,7 @@ time_update (EV_P_ ev_tstamp max_block)
|
||||
}
|
||||
|
||||
void
|
||||
ev_run (EV_P_ int flags)
|
||||
ev_run (EV_P_ ev_tstamp waittime)
|
||||
{
|
||||
#if EV_FEATURE_API
|
||||
++loop_depth;
|
||||
@ -2426,15 +2426,6 @@ ev_run (EV_P_ int flags)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if EV_PREPARE_ENABLE
|
||||
/* queue prepare watchers (and execute them) */
|
||||
if (expect_false (preparecnt))
|
||||
{
|
||||
queue_events (EV_A_ (W *)prepares, preparecnt, EV_PREPARE);
|
||||
EV_INVOKE_PENDING;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (expect_false (loop_done))
|
||||
break;
|
||||
|
||||
@ -2445,90 +2436,16 @@ ev_run (EV_P_ int flags)
|
||||
/* update fd-related kernel structures */
|
||||
fd_reify (EV_A);
|
||||
|
||||
/* calculate blocking time */
|
||||
{
|
||||
ev_tstamp waittime = 0.;
|
||||
ev_tstamp sleeptime = 0.;
|
||||
|
||||
/* remember old timestamp for io_blocktime calculation */
|
||||
ev_tstamp prev_mn_now = mn_now;
|
||||
|
||||
/* update time to cancel out callback processing overhead */
|
||||
time_update (EV_A_ 1e100);
|
||||
|
||||
if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt)))
|
||||
{
|
||||
waittime = MAX_BLOCKTIME;
|
||||
|
||||
if (timercnt)
|
||||
{
|
||||
ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now + backend_fudge;
|
||||
if (waittime > to) waittime = to;
|
||||
}
|
||||
|
||||
#if EV_PERIODIC_ENABLE
|
||||
if (periodiccnt)
|
||||
{
|
||||
ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now + backend_fudge;
|
||||
if (waittime > to) waittime = to;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* don't let timeouts decrease the waittime below timeout_blocktime */
|
||||
if (expect_false (waittime < timeout_blocktime))
|
||||
waittime = timeout_blocktime;
|
||||
|
||||
/* extra check because io_blocktime is commonly 0 */
|
||||
if (expect_false (io_blocktime))
|
||||
{
|
||||
sleeptime = io_blocktime - (mn_now - prev_mn_now);
|
||||
|
||||
if (sleeptime > waittime - backend_fudge)
|
||||
sleeptime = waittime - backend_fudge;
|
||||
|
||||
if (expect_true (sleeptime > 0.))
|
||||
{
|
||||
ev_sleep (sleeptime);
|
||||
waittime -= sleeptime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if EV_FEATURE_API
|
||||
++loop_count;
|
||||
#endif
|
||||
assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */
|
||||
backend_poll (EV_A_ waittime);
|
||||
assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */
|
||||
|
||||
/* update ev_rt_now, do magic */
|
||||
time_update (EV_A_ waittime + sleeptime);
|
||||
}
|
||||
|
||||
/* queue pending timers and reschedule them */
|
||||
timers_reify (EV_A); /* relative timers called last */
|
||||
#if EV_PERIODIC_ENABLE
|
||||
periodics_reify (EV_A); /* absolute timers called first */
|
||||
#endif
|
||||
|
||||
#if EV_IDLE_ENABLE
|
||||
/* queue idle watchers unless other events are pending */
|
||||
idle_reify (EV_A);
|
||||
#endif
|
||||
|
||||
#if EV_CHECK_ENABLE
|
||||
/* queue check watchers, to be executed first */
|
||||
if (expect_false (checkcnt))
|
||||
queue_events (EV_A_ (W *)checks, checkcnt, EV_CHECK);
|
||||
++loop_count;
|
||||
#endif
|
||||
assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */
|
||||
backend_poll (EV_A_ waittime);
|
||||
assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */
|
||||
|
||||
EV_INVOKE_PENDING;
|
||||
}
|
||||
while (expect_true (
|
||||
activecnt
|
||||
&& !loop_done
|
||||
&& !(flags & (EVRUN_ONCE | EVRUN_NOWAIT))
|
||||
));
|
||||
while (0);
|
||||
|
||||
if (loop_done == EVBREAK_ONE)
|
||||
loop_done = EVBREAK_CANCEL;
|
||||
|
24
deps/uv/src/unix/internal.h
vendored
24
deps/uv/src/unix/internal.h
vendored
@ -93,23 +93,9 @@ enum {
|
||||
UV_STREAM_WRITABLE = 0x40, /* The stream is writable */
|
||||
UV_STREAM_BLOCKING = 0x80, /* Synchronous writes. */
|
||||
UV_TCP_NODELAY = 0x100, /* Disable Nagle. */
|
||||
UV_TCP_KEEPALIVE = 0x200, /* Turn on keep-alive. */
|
||||
UV_TIMER_REPEAT = 0x100,
|
||||
UV__PENDING = 0x800
|
||||
UV_TCP_KEEPALIVE = 0x200 /* Turn on keep-alive. */
|
||||
};
|
||||
|
||||
inline static int uv__has_pending_handles(const uv_loop_t* loop) {
|
||||
return loop->pending_handles != NULL;
|
||||
}
|
||||
|
||||
inline static void uv__make_pending(uv_handle_t* h) {
|
||||
if (h->flags & UV__PENDING) return;
|
||||
h->next_pending = h->loop->pending_handles;
|
||||
h->loop->pending_handles = h;
|
||||
h->flags |= UV__PENDING;
|
||||
}
|
||||
#define uv__make_pending(h) uv__make_pending((uv_handle_t*)(h))
|
||||
|
||||
inline static void uv__req_init(uv_loop_t* loop,
|
||||
uv_req_t* req,
|
||||
uv_req_type type) {
|
||||
@ -164,8 +150,9 @@ int uv__tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay);
|
||||
/* pipe */
|
||||
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
|
||||
|
||||
/* poll */
|
||||
void uv__poll_close(uv_poll_t* handle);
|
||||
/* timer */
|
||||
void uv__run_timers(uv_loop_t* loop);
|
||||
unsigned int uv__next_timeout(uv_loop_t* loop);
|
||||
|
||||
/* various */
|
||||
void uv__async_close(uv_async_t* handle);
|
||||
@ -173,6 +160,7 @@ void uv__check_close(uv_check_t* handle);
|
||||
void uv__fs_event_close(uv_fs_event_t* handle);
|
||||
void uv__idle_close(uv_idle_t* handle);
|
||||
void uv__pipe_close(uv_pipe_t* handle);
|
||||
void uv__poll_close(uv_poll_t* handle);
|
||||
void uv__prepare_close(uv_prepare_t* handle);
|
||||
void uv__process_close(uv_process_t* handle);
|
||||
void uv__stream_close(uv_stream_t* handle);
|
||||
@ -180,8 +168,6 @@ void uv__timer_close(uv_timer_t* handle);
|
||||
void uv__udp_close(uv_udp_t* handle);
|
||||
void uv__udp_finish_close(uv_udp_t* handle);
|
||||
|
||||
void uv__stream_pending(uv_stream_t* handle);
|
||||
|
||||
#define UV__F_IPC (1 << 0)
|
||||
#define UV__F_NONBLOCK (1 << 1)
|
||||
int uv__make_socketpair(int fds[2], int flags);
|
||||
|
5
deps/uv/src/unix/loop.c
vendored
5
deps/uv/src/unix/loop.c
vendored
@ -37,12 +37,15 @@ int uv__loop_init(uv_loop_t* loop, int default_loop) {
|
||||
memset(loop, 0, sizeof(*loop));
|
||||
|
||||
RB_INIT(&loop->ares_handles);
|
||||
RB_INIT(&loop->timer_handles);
|
||||
ngx_queue_init(&loop->active_reqs);
|
||||
ngx_queue_init(&loop->idle_handles);
|
||||
ngx_queue_init(&loop->check_handles);
|
||||
ngx_queue_init(&loop->prepare_handles);
|
||||
loop->pending_handles = NULL;
|
||||
ngx_queue_init(&loop->handle_queue);
|
||||
loop->closing_handles = NULL;
|
||||
loop->channel = NULL;
|
||||
loop->time = uv_hrtime() / 1000000;
|
||||
loop->ev = (default_loop ? ev_default_loop : ev_loop_new)(flags);
|
||||
ev_set_userdata(loop->ev, loop);
|
||||
eio_channel_init(&loop->uv_eio_channel, loop);
|
||||
|
2
deps/uv/src/unix/pipe.c
vendored
2
deps/uv/src/unix/pipe.c
vendored
@ -218,7 +218,7 @@ out:
|
||||
ngx_queue_init(&req->queue);
|
||||
|
||||
/* Run callback on next tick. */
|
||||
uv__make_pending(handle);
|
||||
uv__io_feed(handle->loop, &handle->write_watcher, UV__IO_WRITE);
|
||||
|
||||
/* Mimic the Windows pipe implementation, always
|
||||
* return 0 and let the callback handle errors.
|
||||
|
60
deps/uv/src/unix/process.c
vendored
60
deps/uv/src/unix/process.c
vendored
@ -140,33 +140,39 @@ int uv__make_pipe(int fds[2], int flags) {
|
||||
*/
|
||||
static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2],
|
||||
int writable) {
|
||||
if (container->flags == UV_IGNORE) {
|
||||
return 0;
|
||||
} else if (container->flags & UV_CREATE_PIPE) {
|
||||
assert(container->data.stream != NULL);
|
||||
int fd = -1;
|
||||
switch (container->flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD |
|
||||
UV_INHERIT_STREAM)) {
|
||||
case UV_IGNORE:
|
||||
return 0;
|
||||
case UV_CREATE_PIPE:
|
||||
assert(container->data.stream != NULL);
|
||||
|
||||
if (container->data.stream->type != UV_NAMED_PIPE) {
|
||||
errno = EINVAL;
|
||||
if (container->data.stream->type != UV_NAMED_PIPE) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return uv__make_socketpair(fds, 0);
|
||||
case UV_INHERIT_FD:
|
||||
case UV_INHERIT_STREAM:
|
||||
if (container->flags & UV_INHERIT_FD) {
|
||||
fd = container->data.fd;
|
||||
} else {
|
||||
fd = container->data.stream->fd;
|
||||
}
|
||||
|
||||
if (fd == -1) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fds[writable ? 1 : 0] = fd;
|
||||
|
||||
return 0;
|
||||
default:
|
||||
assert(0 && "Unexpected flags");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return uv__make_socketpair(fds, 0);
|
||||
} else if (container->flags & UV_RAW_FD) {
|
||||
if (container->data.fd == -1) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (writable) {
|
||||
fds[1] = container->data.fd;
|
||||
} else {
|
||||
fds[0] = container->data.fd;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
assert(0 && "Unexpected flags");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,6 +246,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
||||
|
||||
assert(options.file != NULL);
|
||||
assert(!(options.flags & ~(UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS |
|
||||
UV_PROCESS_DETACHED |
|
||||
UV_PROCESS_SETGID |
|
||||
UV_PROCESS_SETUID)));
|
||||
|
||||
@ -301,6 +308,9 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
||||
|
||||
if (pid == 0) {
|
||||
/* Child */
|
||||
if (options.flags & UV_PROCESS_DETACHED) {
|
||||
setsid();
|
||||
}
|
||||
|
||||
/* Dup fds */
|
||||
for (i = 0; i < options.stdio_count; i++) {
|
||||
|
7
deps/uv/src/unix/stream.c
vendored
7
deps/uv/src/unix/stream.c
vendored
@ -718,11 +718,6 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
|
||||
}
|
||||
|
||||
|
||||
void uv__stream_pending(uv_stream_t* handle) {
|
||||
uv__stream_io(handle->loop, &handle->write_watcher, UV__IO_WRITE);
|
||||
}
|
||||
|
||||
|
||||
static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, int events) {
|
||||
uv_stream_t* stream;
|
||||
|
||||
@ -859,7 +854,7 @@ int uv__connect(uv_connect_t* req, uv_stream_t* stream, struct sockaddr* addr,
|
||||
uv__io_start(stream->loop, &stream->write_watcher);
|
||||
|
||||
if (stream->delayed_error)
|
||||
uv__make_pending(stream);
|
||||
uv__io_feed(stream->loop, &stream->write_watcher, UV__IO_WRITE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
122
deps/uv/src/unix/timer.c
vendored
122
deps/uv/src/unix/timer.c
vendored
@ -22,92 +22,114 @@
|
||||
#include "internal.h"
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
static int uv__timer_repeating(const uv_timer_t* timer) {
|
||||
return timer->flags & UV_TIMER_REPEAT;
|
||||
static int uv__timer_cmp(const uv_timer_t* a, const uv_timer_t* b) {
|
||||
if (a->timeout < b->timeout)
|
||||
return -1;
|
||||
if (a->timeout > b->timeout)
|
||||
return 1;
|
||||
if (a < b)
|
||||
return -1;
|
||||
if (a > b)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void uv__timer_cb(EV_P_ ev_timer* w, int revents) {
|
||||
uv_timer_t* timer = container_of(w, uv_timer_t, timer_watcher);
|
||||
|
||||
if (!uv__is_active(timer))
|
||||
return;
|
||||
|
||||
if (!uv__timer_repeating(timer))
|
||||
uv__handle_stop(timer);
|
||||
|
||||
if (timer->timer_cb)
|
||||
timer->timer_cb(timer, 0);
|
||||
}
|
||||
RB_GENERATE_STATIC(uv__timers, uv_timer_s, tree_entry, uv__timer_cmp)
|
||||
|
||||
|
||||
int uv_timer_init(uv_loop_t* loop, uv_timer_t* timer) {
|
||||
uv__handle_init(loop, (uv_handle_t*)timer, UV_TIMER);
|
||||
int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
|
||||
loop->counters.timer_init++;
|
||||
|
||||
ev_init(&timer->timer_watcher, uv__timer_cb);
|
||||
uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER);
|
||||
handle->timer_cb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_timer_start(uv_timer_t* timer,
|
||||
int uv_timer_start(uv_timer_t* handle,
|
||||
uv_timer_cb cb,
|
||||
int64_t timeout,
|
||||
int64_t repeat) {
|
||||
if (uv__is_active(timer))
|
||||
uv_timer_stop(timer);
|
||||
assert(timeout >= 0);
|
||||
assert(repeat >= 0);
|
||||
|
||||
timer->timer_cb = cb;
|
||||
if (uv__is_active(handle))
|
||||
uv_timer_stop(handle);
|
||||
|
||||
if (repeat)
|
||||
timer->flags |= UV_TIMER_REPEAT;
|
||||
else
|
||||
timer->flags &= ~UV_TIMER_REPEAT;
|
||||
handle->timer_cb = cb;
|
||||
handle->timeout = handle->loop->time + timeout;
|
||||
handle->repeat = repeat;
|
||||
|
||||
ev_timer_set(&timer->timer_watcher, timeout / 1000.0, repeat / 1000.0);
|
||||
ev_timer_start(timer->loop->ev, &timer->timer_watcher);
|
||||
uv__handle_start(timer);
|
||||
RB_INSERT(uv__timers, &handle->loop->timer_handles, handle);
|
||||
uv__handle_start(handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_timer_stop(uv_timer_t* timer) {
|
||||
timer->flags &= ~UV_TIMER_REPEAT;
|
||||
ev_timer_stop(timer->loop->ev, &timer->timer_watcher);
|
||||
uv__handle_stop(timer);
|
||||
int uv_timer_stop(uv_timer_t* handle) {
|
||||
if (!uv__is_active(handle))
|
||||
return 0;
|
||||
|
||||
RB_REMOVE(uv__timers, &handle->loop->timer_handles, handle);
|
||||
uv__handle_stop(handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_timer_again(uv_timer_t* timer) {
|
||||
if (!uv__is_active(timer)) {
|
||||
uv__set_artificial_error(timer->loop, UV_EINVAL);
|
||||
return -1;
|
||||
int uv_timer_again(uv_timer_t* handle) {
|
||||
if (handle->timer_cb == NULL)
|
||||
return uv__set_artificial_error(handle->loop, UV_EINVAL);
|
||||
|
||||
if (handle->repeat) {
|
||||
uv_timer_stop(handle);
|
||||
uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat);
|
||||
}
|
||||
|
||||
assert(uv__timer_repeating(timer));
|
||||
ev_timer_again(timer->loop->ev, &timer->timer_watcher);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uv_timer_set_repeat(uv_timer_t* timer, int64_t repeat) {
|
||||
assert(timer->type == UV_TIMER);
|
||||
timer->timer_watcher.repeat = repeat / 1000.0;
|
||||
|
||||
if (repeat)
|
||||
timer->flags |= UV_TIMER_REPEAT;
|
||||
else
|
||||
timer->flags &= ~UV_TIMER_REPEAT;
|
||||
void uv_timer_set_repeat(uv_timer_t* handle, int64_t repeat) {
|
||||
assert(repeat >= 0);
|
||||
handle->repeat = repeat;
|
||||
}
|
||||
|
||||
|
||||
int64_t uv_timer_get_repeat(uv_timer_t* timer) {
|
||||
assert(timer->type == UV_TIMER);
|
||||
return (int64_t)(1000 * timer->timer_watcher.repeat);
|
||||
int64_t uv_timer_get_repeat(uv_timer_t* handle) {
|
||||
return handle->repeat;
|
||||
}
|
||||
|
||||
|
||||
unsigned int uv__next_timeout(uv_loop_t* loop) {
|
||||
uv_timer_t* handle;
|
||||
|
||||
handle = RB_MIN(uv__timers, &loop->timer_handles);
|
||||
|
||||
if (handle == NULL)
|
||||
return (unsigned int) -1; /* block indefinitely */
|
||||
|
||||
if (handle->timeout <= loop->time)
|
||||
return 0;
|
||||
|
||||
return handle->timeout - loop->time;
|
||||
}
|
||||
|
||||
|
||||
void uv__run_timers(uv_loop_t* loop) {
|
||||
uv_timer_t* handle;
|
||||
|
||||
while ((handle = RB_MIN(uv__timers, &loop->timer_handles))) {
|
||||
if (handle->timeout > loop->time)
|
||||
break;
|
||||
|
||||
uv_timer_stop(handle);
|
||||
uv_timer_again(handle);
|
||||
handle->timer_cb(handle, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
14
deps/uv/src/unix/uv-eio.c
vendored
14
deps/uv/src/unix/uv-eio.c
vendored
@ -22,6 +22,7 @@
|
||||
|
||||
#include "uv.h"
|
||||
#include "eio.h"
|
||||
#include "internal.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
@ -87,13 +88,18 @@ void uv_eio_init(uv_loop_t* loop) {
|
||||
|
||||
uv_idle_init(loop, &loop->uv_eio_poller);
|
||||
uv_idle_start(&loop->uv_eio_poller, uv_eio_do_poll);
|
||||
loop->uv_eio_poller.flags |= UV__HANDLE_INTERNAL;
|
||||
|
||||
loop->uv_eio_want_poll_notifier.data = loop;
|
||||
uv_async_init(loop, &loop->uv_eio_want_poll_notifier,
|
||||
uv_eio_want_poll_notifier_cb);
|
||||
uv_async_init(loop,
|
||||
&loop->uv_eio_want_poll_notifier,
|
||||
uv_eio_want_poll_notifier_cb);
|
||||
loop->uv_eio_want_poll_notifier.flags |= UV__HANDLE_INTERNAL;
|
||||
|
||||
uv_async_init(loop, &loop->uv_eio_done_poll_notifier,
|
||||
uv_eio_done_poll_notifier_cb);
|
||||
uv_async_init(loop,
|
||||
&loop->uv_eio_done_poll_notifier,
|
||||
uv_eio_done_poll_notifier_cb);
|
||||
loop->uv_eio_done_poll_notifier.flags |= UV__HANDLE_INTERNAL;
|
||||
|
||||
uv_once(&uv__eio_init_once_guard, uv__eio_init);
|
||||
}
|
||||
|
12
deps/uv/src/uv-common.c
vendored
12
deps/uv/src/uv-common.c
vendored
@ -317,6 +317,18 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
|
||||
}
|
||||
|
||||
|
||||
void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
|
||||
ngx_queue_t* q;
|
||||
uv_handle_t* h;
|
||||
|
||||
ngx_queue_foreach(q, &loop->handle_queue) {
|
||||
h = ngx_queue_data(q, uv_handle_t, handle_queue);
|
||||
if (h->flags & UV__HANDLE_INTERNAL) continue;
|
||||
walk_cb(h, arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uv_ref(uv_handle_t* handle) {
|
||||
uv__handle_ref(handle);
|
||||
}
|
||||
|
36
deps/uv/src/uv-common.h
vendored
36
deps/uv/src/uv-common.h
vendored
@ -49,12 +49,14 @@
|
||||
|
||||
#ifndef _WIN32
|
||||
enum {
|
||||
UV__ACTIVE = 0x4000,
|
||||
UV__REF = 0x8000
|
||||
UV__HANDLE_INTERNAL = 0x8000,
|
||||
UV__HANDLE_ACTIVE = 0x4000,
|
||||
UV__HANDLE_REF = 0x2000
|
||||
};
|
||||
#else
|
||||
# define UV__REF 0x00000020
|
||||
# define UV__ACTIVE 0x00000040
|
||||
# define UV__HANDLE_INTERNAL 0x80
|
||||
# define UV__HANDLE_ACTIVE 0x40
|
||||
# define UV__HANDLE_REF 0x20
|
||||
#endif
|
||||
|
||||
extern const uv_err_t uv_ok_;
|
||||
@ -117,35 +119,35 @@ UNUSED static void uv__active_handle_rm(uv_handle_t* h) {
|
||||
#define uv__req_unregister(loop, req) uv__req_unregister((loop), (uv_req_t*)(req))
|
||||
|
||||
UNUSED static int uv__is_active(const uv_handle_t* h) {
|
||||
return !!(h->flags & UV__ACTIVE);
|
||||
return !!(h->flags & UV__HANDLE_ACTIVE);
|
||||
}
|
||||
#define uv__is_active(h) uv__is_active((const uv_handle_t*)(h))
|
||||
|
||||
UNUSED static void uv__handle_start(uv_handle_t* h) {
|
||||
if (h->flags & UV__ACTIVE) return;
|
||||
if (h->flags & UV__REF) uv__active_handle_add(h);
|
||||
h->flags |= UV__ACTIVE;
|
||||
if (h->flags & UV__HANDLE_ACTIVE) return;
|
||||
if (h->flags & UV__HANDLE_REF) uv__active_handle_add(h);
|
||||
h->flags |= UV__HANDLE_ACTIVE;
|
||||
}
|
||||
#define uv__handle_start(h) uv__handle_start((uv_handle_t*)(h))
|
||||
|
||||
UNUSED static void uv__handle_stop(uv_handle_t* h) {
|
||||
if (!(h->flags & UV__ACTIVE)) return;
|
||||
if (h->flags & UV__REF) uv__active_handle_rm(h);
|
||||
h->flags &= ~UV__ACTIVE;
|
||||
if (!(h->flags & UV__HANDLE_ACTIVE)) return;
|
||||
if (h->flags & UV__HANDLE_REF) uv__active_handle_rm(h);
|
||||
h->flags &= ~UV__HANDLE_ACTIVE;
|
||||
}
|
||||
#define uv__handle_stop(h) uv__handle_stop((uv_handle_t*)(h))
|
||||
|
||||
UNUSED static void uv__handle_ref(uv_handle_t* h) {
|
||||
if (h->flags & UV__REF) return;
|
||||
if (h->flags & UV__ACTIVE) uv__active_handle_add(h);
|
||||
h->flags |= UV__REF;
|
||||
if (h->flags & UV__HANDLE_REF) return;
|
||||
if (h->flags & UV__HANDLE_ACTIVE) uv__active_handle_add(h);
|
||||
h->flags |= UV__HANDLE_REF;
|
||||
}
|
||||
#define uv__handle_ref(h) uv__handle_ref((uv_handle_t*)(h))
|
||||
|
||||
UNUSED static void uv__handle_unref(uv_handle_t* h) {
|
||||
if (!(h->flags & UV__REF)) return;
|
||||
if (h->flags & UV__ACTIVE) uv__active_handle_rm(h);
|
||||
h->flags &= ~UV__REF;
|
||||
if (!(h->flags & UV__HANDLE_REF)) return;
|
||||
if (h->flags & UV__HANDLE_ACTIVE) uv__active_handle_rm(h);
|
||||
h->flags &= ~UV__HANDLE_REF;
|
||||
}
|
||||
#define uv__handle_unref(h) uv__handle_unref((uv_handle_t*)(h))
|
||||
|
||||
|
6
deps/uv/src/win/async.c
vendored
6
deps/uv/src/win/async.c
vendored
@ -58,12 +58,8 @@ void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle) {
|
||||
if (handle->flags & UV_HANDLE_CLOSING &&
|
||||
!handle->async_sent) {
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||
handle->flags |= UV_HANDLE_CLOSED;
|
||||
uv__handle_stop(handle);
|
||||
|
||||
if (handle->close_cb) {
|
||||
handle->close_cb((uv_handle_t*)handle);
|
||||
}
|
||||
uv__handle_close(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
1
deps/uv/src/win/core.c
vendored
1
deps/uv/src/win/core.c
vendored
@ -66,6 +66,7 @@ static void uv_loop_init(uv_loop_t* loop) {
|
||||
|
||||
uv_update_time(loop);
|
||||
|
||||
ngx_queue_init(&loop->handle_queue);
|
||||
ngx_queue_init(&loop->active_reqs);
|
||||
loop->active_handles = 0;
|
||||
|
||||
|
5
deps/uv/src/win/fs-event.c
vendored
5
deps/uv/src/win/fs-event.c
vendored
@ -479,7 +479,6 @@ void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
|
||||
if (handle->flags & UV_HANDLE_CLOSING &&
|
||||
!handle->req_pending) {
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||
handle->flags |= UV_HANDLE_CLOSED;
|
||||
uv__handle_stop(handle);
|
||||
|
||||
if (handle->buffer) {
|
||||
@ -507,8 +506,6 @@ void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
|
||||
handle->dirw = NULL;
|
||||
}
|
||||
|
||||
if (handle->close_cb) {
|
||||
handle->close_cb((uv_handle_t*)handle);
|
||||
}
|
||||
uv__handle_close(handle);
|
||||
}
|
||||
}
|
||||
|
6
deps/uv/src/win/handle.c
vendored
6
deps/uv/src/win/handle.c
vendored
@ -57,13 +57,15 @@ uv_handle_type uv_guess_handle(uv_file file) {
|
||||
|
||||
|
||||
int uv_is_active(const uv_handle_t* handle) {
|
||||
return (handle->flags & UV__ACTIVE) && !(handle->flags & UV_HANDLE_CLOSING);
|
||||
return (handle->flags & UV__HANDLE_ACTIVE) &&
|
||||
!(handle->flags & UV_HANDLE_CLOSING);
|
||||
}
|
||||
|
||||
|
||||
void uv_handle_init(uv_loop_t* loop, uv_handle_t* handle) {
|
||||
handle->loop = loop;
|
||||
handle->flags = UV__REF;
|
||||
handle->flags = UV__HANDLE_REF;
|
||||
ngx_queue_insert_tail(&loop->handle_queue, &handle->handle_queue);
|
||||
|
||||
loop->counters.handle_init++;
|
||||
}
|
||||
|
13
deps/uv/src/win/internal.h
vendored
13
deps/uv/src/win/internal.h
vendored
@ -40,9 +40,8 @@
|
||||
#define UV_HANDLE_ENDGAME_QUEUED 0x00000004
|
||||
#define UV_HANDLE_ACTIVE 0x00000010
|
||||
|
||||
/* Keep in sync with uv-common.h: */
|
||||
#define UV__REF 0x00000020
|
||||
#define UV__ACTIVE 0x00000040
|
||||
/* uv-common.h: #define UV__HANDLE_ACTIVE 0x00000040 */
|
||||
/* uv-common.h: #define UV__HANDLE_REF 0x00000020 */
|
||||
/* reserved: #define UV_HANDLE_INTERNAL 0x00000080 */
|
||||
|
||||
/* Used by streams and UDP handles. */
|
||||
@ -131,6 +130,14 @@ void uv_process_endgames(uv_loop_t* loop);
|
||||
uv__req_unregister((loop), (req)); \
|
||||
} while (0)
|
||||
|
||||
#define uv__handle_close(handle) \
|
||||
do { \
|
||||
ngx_queue_remove(&(handle)->handle_queue); \
|
||||
(handle)->flags |= UV_HANDLE_CLOSED; \
|
||||
if ((handle)->close_cb) { \
|
||||
(handle)->close_cb((uv_handle_t*)(handle)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Handles
|
||||
|
5
deps/uv/src/win/loop-watcher.c
vendored
5
deps/uv/src/win/loop-watcher.c
vendored
@ -30,10 +30,7 @@ void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) {
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||
handle->flags |= UV_HANDLE_CLOSED;
|
||||
uv__handle_stop(handle);
|
||||
|
||||
if (handle->close_cb) {
|
||||
handle->close_cb(handle);
|
||||
}
|
||||
uv__handle_close(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
7
deps/uv/src/win/pipe.c
vendored
7
deps/uv/src/win/pipe.c
vendored
@ -164,7 +164,7 @@ int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
|
||||
int err;
|
||||
char* ptr = (char*)handle;
|
||||
|
||||
while (TRUE) {
|
||||
for (;;) {
|
||||
uv_unique_pipe_name(ptr, name, nameSize);
|
||||
|
||||
pipeHandle = CreateNamedPipeA(name,
|
||||
@ -358,7 +358,6 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
|
||||
if (handle->flags & UV_HANDLE_CLOSING &&
|
||||
handle->reqs_pending == 0) {
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||
handle->flags |= UV_HANDLE_CLOSED;
|
||||
uv__handle_stop(handle);
|
||||
|
||||
if (handle->flags & UV_HANDLE_CONNECTION) {
|
||||
@ -385,9 +384,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
|
||||
handle->accept_reqs = NULL;
|
||||
}
|
||||
|
||||
if (handle->close_cb) {
|
||||
handle->close_cb((uv_handle_t*)handle);
|
||||
}
|
||||
uv__handle_close(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
20
deps/uv/src/win/poll.c
vendored
20
deps/uv/src/win/poll.c
vendored
@ -94,7 +94,7 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
|
||||
}
|
||||
|
||||
|
||||
static int uv__fast_poll_cancel_poll_reqs(uv_loop_t* loop, uv_poll_t* handle) {
|
||||
static int uv__fast_poll_cancel_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
|
||||
AFD_POLL_INFO afd_poll_info;
|
||||
DWORD result;
|
||||
HANDLE event;
|
||||
@ -106,15 +106,15 @@ static int uv__fast_poll_cancel_poll_reqs(uv_loop_t* loop, uv_poll_t* handle) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
afd_poll_info.Exclusive = TRUE;
|
||||
afd_poll_info.Exclusive = FALSE;
|
||||
afd_poll_info.NumberOfHandles = 1;
|
||||
afd_poll_info.Timeout.QuadPart = INT64_MAX;
|
||||
afd_poll_info.Timeout.QuadPart = 0;
|
||||
afd_poll_info.Handles[0].Handle = (HANDLE) handle->socket;
|
||||
afd_poll_info.Handles[0].Status = 0;
|
||||
afd_poll_info.Handles[0].Events = AFD_POLL_ALL;
|
||||
|
||||
memset(&overlapped, 0, sizeof overlapped);
|
||||
overlapped.hEvent = (HANDLE) ((uintptr_t) event & 1);
|
||||
overlapped.hEvent = (HANDLE) ((uintptr_t) event | 1);
|
||||
|
||||
result = uv_msafd_poll(handle->socket,
|
||||
&afd_poll_info,
|
||||
@ -129,6 +129,10 @@ static int uv__fast_poll_cancel_poll_reqs(uv_loop_t* loop, uv_poll_t* handle) {
|
||||
}
|
||||
}
|
||||
|
||||
if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0) {
|
||||
uv_fatal_error(GetLastError(), "WaitForSingleObject");
|
||||
}
|
||||
|
||||
CloseHandle(event);
|
||||
return 0;
|
||||
}
|
||||
@ -234,7 +238,7 @@ static void uv__fast_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
|
||||
pCancelIoEx((HANDLE) handle->socket, &handle->poll_req_2.overlapped);
|
||||
} else if (handle->submitted_events_1 | handle->submitted_events_2) {
|
||||
/* Execute another unique poll to force the others to return. */
|
||||
uv__fast_poll_cancel_poll_reqs(loop, handle);
|
||||
uv__fast_poll_cancel_poll_req(loop, handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -611,10 +615,6 @@ void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) {
|
||||
assert(handle->submitted_events_1 == 0);
|
||||
assert(handle->submitted_events_2 == 0);
|
||||
|
||||
handle->flags |= UV_HANDLE_CLOSED;
|
||||
uv__handle_stop(handle);
|
||||
|
||||
if (handle->close_cb) {
|
||||
handle->close_cb((uv_handle_t*)handle);
|
||||
}
|
||||
uv__handle_close(handle);
|
||||
}
|
||||
|
579
deps/uv/src/win/process.c
vendored
579
deps/uv/src/win/process.c
vendored
@ -22,15 +22,28 @@
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
#define SIGKILL 9
|
||||
|
||||
|
||||
/* CRT file descriptor mode flags */
|
||||
#define FOPEN 0x01
|
||||
#define FEOFLAG 0x02
|
||||
#define FCRLF 0x04
|
||||
#define FPIPE 0x08
|
||||
#define FNOINHERIT 0x10
|
||||
#define FAPPEND 0x20
|
||||
#define FDEV 0x40
|
||||
#define FTEXT 0x80
|
||||
|
||||
|
||||
typedef struct env_var {
|
||||
const char* narrow;
|
||||
const wchar_t* wide;
|
||||
@ -41,6 +54,7 @@ typedef struct env_var {
|
||||
|
||||
#define E_V(str) { str "=", L##str, sizeof(str), 0, 0 }
|
||||
|
||||
|
||||
#define UTF8_TO_UTF16(s, t) \
|
||||
size = uv_utf8_to_utf16(s, NULL, 0) * sizeof(wchar_t); \
|
||||
t = (wchar_t*)malloc(size); \
|
||||
@ -54,6 +68,37 @@ typedef struct env_var {
|
||||
}
|
||||
|
||||
|
||||
/* The `child_stdio_buffer` buffer has the following layout:
|
||||
* int number_of_fds
|
||||
* unsigned char crt_flags[number_of_fds]
|
||||
* HANDLE os_handle[number_of_fds]
|
||||
*/
|
||||
|
||||
#define CHILD_STDIO_SIZE(count) \
|
||||
(sizeof(int) + \
|
||||
sizeof(unsigned char) * (count) + \
|
||||
sizeof(uintptr_t) * (count))
|
||||
|
||||
#define CHILD_STDIO_COUNT(buffer) \
|
||||
*((unsigned int*) (buffer))
|
||||
|
||||
#define CHILD_STDIO_LPRESERVED2(buffer) \
|
||||
((LPBYTE) (buffer))
|
||||
|
||||
#define CHILD_STDIO_CBRESERVED2(buffer) \
|
||||
CHILD_STDIO_SIZE(CHILD_STDIO_COUNT((buffer)))
|
||||
|
||||
#define CHILD_STDIO_CRT_FLAGS(buffer, fd) \
|
||||
*((unsigned char*) (buffer) + sizeof(int) + fd)
|
||||
|
||||
#define CHILD_STDIO_HANDLE(buffer, fd) \
|
||||
*((HANDLE*) ((unsigned char*) (buffer) + \
|
||||
sizeof(int) + \
|
||||
sizeof(unsigned char) * \
|
||||
CHILD_STDIO_COUNT((buffer)) + \
|
||||
sizeof(HANDLE) * (fd)))
|
||||
|
||||
|
||||
static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) {
|
||||
uv_handle_init(loop, (uv_handle_t*) handle);
|
||||
handle->type = UV_PROCESS;
|
||||
@ -63,9 +108,7 @@ static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) {
|
||||
handle->wait_handle = INVALID_HANDLE_VALUE;
|
||||
handle->process_handle = INVALID_HANDLE_VALUE;
|
||||
handle->close_handle = INVALID_HANDLE_VALUE;
|
||||
handle->child_stdio[0] = INVALID_HANDLE_VALUE;
|
||||
handle->child_stdio[1] = INVALID_HANDLE_VALUE;
|
||||
handle->child_stdio[2] = INVALID_HANDLE_VALUE;
|
||||
handle->child_stdio_buffer = NULL;
|
||||
|
||||
uv_req_init(loop, (uv_req_t*)&handle->exit_req);
|
||||
handle->exit_req.type = UV_PROCESS_EXIT;
|
||||
@ -594,6 +637,153 @@ wchar_t* make_program_env(char** env_block) {
|
||||
}
|
||||
|
||||
|
||||
static int uv_create_stdio_pipe_pair(uv_loop_t* loop, uv_pipe_t* server_pipe,
|
||||
HANDLE* child_pipe_ptr, unsigned int flags) {
|
||||
char pipe_name[64];
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
DWORD server_access = 0;
|
||||
DWORD client_access = 0;
|
||||
HANDLE child_pipe = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (flags & UV_READABLE_PIPE) {
|
||||
server_access |= PIPE_ACCESS_OUTBOUND;
|
||||
client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
|
||||
}
|
||||
if (flags & UV_WRITABLE_PIPE) {
|
||||
server_access |= PIPE_ACCESS_INBOUND;
|
||||
client_access |= GENERIC_WRITE;
|
||||
}
|
||||
|
||||
/* Create server pipe handle. */
|
||||
if (uv_stdio_pipe_server(loop,
|
||||
server_pipe,
|
||||
server_access,
|
||||
pipe_name,
|
||||
sizeof(pipe_name)) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Create child pipe handle. */
|
||||
sa.nLength = sizeof sa;
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
sa.bInheritHandle = TRUE;
|
||||
|
||||
child_pipe = CreateFileA(pipe_name,
|
||||
client_access,
|
||||
0,
|
||||
&sa,
|
||||
OPEN_EXISTING,
|
||||
server_pipe->ipc ? FILE_FLAG_OVERLAPPED : 0,
|
||||
NULL);
|
||||
if (child_pipe == INVALID_HANDLE_VALUE) {
|
||||
uv__set_sys_error(loop, GetLastError());
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Validate that the pipe was opened in the right mode. */
|
||||
{
|
||||
DWORD mode;
|
||||
BOOL r = GetNamedPipeHandleState(child_pipe,
|
||||
&mode,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0);
|
||||
assert(r == TRUE);
|
||||
assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Do a blocking ConnectNamedPipe. This should not block because we have */
|
||||
/* both ends of the pipe created. */
|
||||
if (!ConnectNamedPipe(server_pipe->handle, NULL)) {
|
||||
if (GetLastError() != ERROR_PIPE_CONNECTED) {
|
||||
uv__set_sys_error(loop, GetLastError());
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
*child_pipe_ptr = child_pipe;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (server_pipe->handle != INVALID_HANDLE_VALUE) {
|
||||
uv_pipe_cleanup(loop, server_pipe);
|
||||
}
|
||||
|
||||
if (child_pipe != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(child_pipe);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) {
|
||||
HANDLE current_process;
|
||||
|
||||
current_process = GetCurrentProcess();
|
||||
|
||||
if (!DuplicateHandle(current_process,
|
||||
handle,
|
||||
current_process,
|
||||
dup,
|
||||
0,
|
||||
TRUE,
|
||||
DUPLICATE_SAME_ACCESS)) {
|
||||
*dup = INVALID_HANDLE_VALUE;
|
||||
uv__set_sys_error(loop, GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int duplicate_fd(uv_loop_t* loop, int fd, HANDLE* dup) {
|
||||
HANDLE handle;
|
||||
|
||||
if (fd == -1) {
|
||||
*dup = INVALID_HANDLE_VALUE;
|
||||
uv__set_artificial_error(loop, UV_EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
handle = (HANDLE)_get_osfhandle(fd);
|
||||
return duplicate_handle(loop, handle, dup);
|
||||
}
|
||||
|
||||
|
||||
static void set_child_stdio_noinherit(void* buffer) {
|
||||
int i, count;
|
||||
|
||||
count = CHILD_STDIO_COUNT(buffer);
|
||||
for (i = 0; i < count; i++) {
|
||||
HANDLE handle = CHILD_STDIO_HANDLE(buffer, i);
|
||||
if (handle != INVALID_HANDLE_VALUE) {
|
||||
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void close_and_free_child_stdio(void* buffer) {
|
||||
int i, count;
|
||||
|
||||
count = CHILD_STDIO_COUNT(buffer);
|
||||
for (i = 0; i < count; i++) {
|
||||
HANDLE handle = CHILD_STDIO_HANDLE(buffer, i);
|
||||
if (handle != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(handle);
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called on Windows thread-pool thread to indicate that
|
||||
* a child process has exited.
|
||||
@ -636,7 +826,7 @@ static DWORD WINAPI spawn_failure(void* data) {
|
||||
char unknown[] = "unknown error\n";
|
||||
uv_process_t* process = (uv_process_t*) data;
|
||||
uv_loop_t* loop = process->loop;
|
||||
HANDLE child_stderr = process->child_stdio[2];
|
||||
HANDLE child_stderr = CHILD_STDIO_HANDLE(process->child_stdio_buffer, 2);
|
||||
char* buf = NULL;
|
||||
DWORD count, written;
|
||||
|
||||
@ -670,20 +860,6 @@ static DWORD WINAPI spawn_failure(void* data) {
|
||||
}
|
||||
|
||||
|
||||
static void close_child_stdio(uv_process_t* process) {
|
||||
int i;
|
||||
HANDLE handle;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(process->child_stdio); i++) {
|
||||
handle = process->child_stdio[i];
|
||||
if (handle != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(handle);
|
||||
process->child_stdio[i] = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Called on main thread after a child process has exited. */
|
||||
void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
|
||||
DWORD exit_code;
|
||||
@ -743,158 +919,199 @@ void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
|
||||
void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) {
|
||||
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||
handle->flags |= UV_HANDLE_CLOSED;
|
||||
uv__handle_stop(handle);
|
||||
|
||||
/* Clean-up the process handle. */
|
||||
CloseHandle(handle->process_handle);
|
||||
|
||||
/* Clean up the child stdio ends that may have been left open. */
|
||||
close_child_stdio(handle);
|
||||
|
||||
if (handle->close_cb) {
|
||||
handle->close_cb((uv_handle_t*)handle);
|
||||
if (handle->child_stdio_buffer != NULL) {
|
||||
close_and_free_child_stdio(handle->child_stdio_buffer);
|
||||
}
|
||||
|
||||
uv__handle_close(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int uv_create_stdio_pipe_pair(uv_loop_t* loop, uv_pipe_t* server_pipe,
|
||||
HANDLE* child_pipe, DWORD server_access, DWORD child_access,
|
||||
int overlapped) {
|
||||
int err;
|
||||
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
|
||||
char pipe_name[64];
|
||||
DWORD mode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT;
|
||||
static int init_child_stdio(uv_loop_t* loop, uv_process_options_t* options,
|
||||
void** buffer_ptr) {
|
||||
void* buffer;
|
||||
int count, i;
|
||||
|
||||
if (server_pipe->type != UV_NAMED_PIPE) {
|
||||
uv__set_artificial_error(loop, UV_EINVAL);
|
||||
err = -1;
|
||||
goto done;
|
||||
count = options->stdio_count;
|
||||
|
||||
if (count < 0 || count > 255) {
|
||||
/* Only support FDs 0-255 */
|
||||
uv__set_artificial_error(loop, UV_ENOTSUP);
|
||||
return -1;
|
||||
} else if (count < 3) {
|
||||
/* There should always be at least 3 stdio handles. */
|
||||
count = 3;
|
||||
}
|
||||
|
||||
/* Create server pipe handle. */
|
||||
err = uv_stdio_pipe_server(loop,
|
||||
server_pipe,
|
||||
server_access,
|
||||
pipe_name,
|
||||
sizeof(pipe_name));
|
||||
if (err) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Create child pipe handle. */
|
||||
*child_pipe = CreateFileA(pipe_name,
|
||||
child_access,
|
||||
0,
|
||||
&sa,
|
||||
OPEN_EXISTING,
|
||||
overlapped ? FILE_FLAG_OVERLAPPED : 0,
|
||||
NULL);
|
||||
|
||||
if (*child_pipe == INVALID_HANDLE_VALUE) {
|
||||
uv__set_sys_error(loop, GetLastError());
|
||||
err = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!SetNamedPipeHandleState(*child_pipe, &mode, NULL, NULL)) {
|
||||
uv__set_sys_error(loop, GetLastError());
|
||||
err = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Do a blocking ConnectNamedPipe. This should not block because
|
||||
* we have both ends of the pipe created.
|
||||
*/
|
||||
if (!ConnectNamedPipe(server_pipe->handle, NULL)) {
|
||||
if (GetLastError() != ERROR_PIPE_CONNECTED) {
|
||||
uv__set_sys_error(loop, GetLastError());
|
||||
err = -1;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
err = 0;
|
||||
|
||||
done:
|
||||
if (err) {
|
||||
if (server_pipe->handle != INVALID_HANDLE_VALUE) {
|
||||
uv_pipe_cleanup(loop, server_pipe);
|
||||
}
|
||||
|
||||
if (*child_pipe != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(*child_pipe);
|
||||
*child_pipe = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) {
|
||||
HANDLE current_process;
|
||||
|
||||
current_process = GetCurrentProcess();
|
||||
|
||||
if (!DuplicateHandle(current_process,
|
||||
handle,
|
||||
current_process,
|
||||
dup,
|
||||
0,
|
||||
TRUE,
|
||||
DUPLICATE_SAME_ACCESS)) {
|
||||
*dup = INVALID_HANDLE_VALUE;
|
||||
uv__set_sys_error(loop, GetLastError());
|
||||
/* Allocate the child stdio buffer */
|
||||
buffer = malloc(CHILD_STDIO_SIZE(count));
|
||||
if (buffer == NULL) {
|
||||
uv__set_artificial_error(loop, UV_ENOMEM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can */
|
||||
/* clean up on failure. */
|
||||
CHILD_STDIO_COUNT(buffer) = count;
|
||||
for (i = 0; i < count; i++) {
|
||||
CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
|
||||
CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
for (i = 0; i < options->stdio_count; i++) {
|
||||
uv_stdio_container_t fdopt = options->stdio[i];
|
||||
|
||||
switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD |
|
||||
UV_INHERIT_STREAM)) {
|
||||
case UV_IGNORE:
|
||||
/* The child is not supposed to inherit this handle. It has already */
|
||||
/* been initialized to INVALID_HANDLE_VALUE, so just keep it like */
|
||||
/* that. */
|
||||
continue;
|
||||
|
||||
case UV_CREATE_PIPE: {
|
||||
/* Create a pair of two connected pipe ends; one end is turned into */
|
||||
/* an uv_pipe_t for use by the parent. The other one is given to */
|
||||
/* the child. */
|
||||
uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream;
|
||||
HANDLE child_pipe;
|
||||
|
||||
/* Create a new, connected pipe pair. stdio[i].stream should point */
|
||||
/* to an uninitialized, but not connected pipe handle. */
|
||||
assert(fdopt.data.stream->type == UV_NAMED_PIPE);
|
||||
assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION));
|
||||
assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER));
|
||||
|
||||
if (uv_create_stdio_pipe_pair(loop,
|
||||
parent_pipe,
|
||||
&child_pipe,
|
||||
fdopt.flags) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
CHILD_STDIO_HANDLE(buffer, i) = child_pipe;
|
||||
CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;
|
||||
break;
|
||||
}
|
||||
|
||||
case UV_INHERIT_FD: {
|
||||
/* Inherit a raw FD. */
|
||||
HANDLE child_handle;
|
||||
|
||||
/* Make an inheritable duplicate of the handle. */
|
||||
if (duplicate_fd(loop, fdopt.data.fd, &child_handle) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Figure out what the type is. */
|
||||
switch (GetFileType(child_handle)) {
|
||||
case FILE_TYPE_DISK:
|
||||
CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN;
|
||||
break;
|
||||
|
||||
case FILE_TYPE_PIPE:
|
||||
CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;
|
||||
|
||||
case FILE_TYPE_CHAR:
|
||||
case FILE_TYPE_REMOTE:
|
||||
CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
|
||||
break;
|
||||
|
||||
case FILE_TYPE_UNKNOWN:
|
||||
if (GetLastError != 0) {
|
||||
uv__set_sys_error(loop, GetLastError());
|
||||
CloseHandle(child_handle);
|
||||
goto error;
|
||||
}
|
||||
CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
CHILD_STDIO_HANDLE(buffer, i) = child_handle;
|
||||
break;
|
||||
}
|
||||
|
||||
case UV_INHERIT_STREAM: {
|
||||
/* Use an existing stream as the stdio handle for the child. */
|
||||
HANDLE stream_handle, child_handle;
|
||||
unsigned char crt_flags;
|
||||
uv_stream_t* stream = fdopt.data.stream;
|
||||
|
||||
/* Leech the handle out of the stream. */
|
||||
if (stream->type = UV_TTY) {
|
||||
stream_handle = ((uv_tty_t*) stream)->handle;
|
||||
crt_flags = FOPEN | FDEV;
|
||||
} else if (stream->type == UV_NAMED_PIPE &&
|
||||
stream->flags & UV_HANDLE_CONNECTED) {
|
||||
stream_handle = ((uv_pipe_t*) stream)->handle;
|
||||
crt_flags = FOPEN | FPIPE;
|
||||
} else {
|
||||
stream_handle = INVALID_HANDLE_VALUE;
|
||||
crt_flags = 0;
|
||||
}
|
||||
|
||||
if (stream_handle == NULL ||
|
||||
stream_handle == INVALID_HANDLE_VALUE) {
|
||||
/* The handle is already closed, or not yet created, or the */
|
||||
/* stream type is not supported. */
|
||||
uv__set_artificial_error(loop, UV_ENOTSUP);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Make an inheritable copy of the handle. */
|
||||
if (duplicate_handle(loop,
|
||||
stream_handle,
|
||||
&child_handle) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
CHILD_STDIO_HANDLE(buffer, i) = child_handle;
|
||||
CHILD_STDIO_CRT_FLAGS(buffer, i) = crt_flags;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
*buffer_ptr = buffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int duplicate_fd(uv_loop_t* loop, int fd, HANDLE* dup) {
|
||||
HANDLE handle;
|
||||
|
||||
if (fd == -1) {
|
||||
*dup = INVALID_HANDLE_VALUE;
|
||||
uv__set_artificial_error(loop, UV_EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
handle = (HANDLE)_get_osfhandle(fd);
|
||||
return duplicate_handle(loop, handle, dup);
|
||||
error:
|
||||
close_and_free_child_stdio(buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
||||
uv_process_options_t options) {
|
||||
int err = 0, keep_child_stdio_open = 0;
|
||||
int size, err = 0, keep_child_stdio_open = 0;
|
||||
wchar_t* path = NULL;
|
||||
int size, i, overlapped;
|
||||
DWORD server_access, child_access;
|
||||
BOOL result;
|
||||
wchar_t* application_path = NULL, *application = NULL, *arguments = NULL,
|
||||
*env = NULL, *cwd = NULL;
|
||||
HANDLE* child_stdio = process->child_stdio;
|
||||
*env = NULL, *cwd = NULL;
|
||||
STARTUPINFOW startup;
|
||||
PROCESS_INFORMATION info;
|
||||
uv_pipe_t* pipe;
|
||||
DWORD process_flags;
|
||||
|
||||
if (options.flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) {
|
||||
uv__set_artificial_error(loop, UV_ENOTSUP);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Only support FDs 0-2 */
|
||||
if (options.stdio_count > 3) {
|
||||
uv__set_artificial_error(loop, UV_ENOTSUP);
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(options.file != NULL);
|
||||
assert(!(options.flags & ~(UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS |
|
||||
UV_PROCESS_DETACHED |
|
||||
UV_PROCESS_SETGID |
|
||||
UV_PROCESS_SETUID)));
|
||||
|
||||
@ -913,8 +1130,11 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
||||
if (size) {
|
||||
cwd = (wchar_t*)malloc(size);
|
||||
if (!cwd) {
|
||||
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
||||
uv__set_artificial_error(loop, UV_ENOMEM);
|
||||
err = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
GetCurrentDirectoryW(size, cwd);
|
||||
} else {
|
||||
uv__set_sys_error(loop, GetLastError());
|
||||
@ -942,60 +1162,10 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
||||
application_path = application;
|
||||
}
|
||||
|
||||
for (i = 0; i < options.stdio_count || i < 3; i++) {
|
||||
if (i >= options.stdio_count ||
|
||||
options.stdio[i].flags == UV_IGNORE) {
|
||||
child_stdio[i] = INVALID_HANDLE_VALUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (options.stdio[i].flags & UV_RAW_FD) {
|
||||
err = duplicate_fd(loop, options.stdio[i].data.fd, &child_stdio[i]);
|
||||
} else if (options.stdio[i].data.stream->type == UV_NAMED_PIPE) {
|
||||
pipe = (uv_pipe_t*)options.stdio[i].data.stream;
|
||||
|
||||
if (options.stdio[i].flags & UV_CREATE_PIPE) {
|
||||
server_access = 0;
|
||||
child_access = 0;
|
||||
if (pipe->ipc) {
|
||||
server_access = PIPE_ACCESS_DUPLEX;
|
||||
child_access = GENERIC_READ | FILE_WRITE_ATTRIBUTES | GENERIC_WRITE;
|
||||
overlapped = 1;
|
||||
} else {
|
||||
overlapped = 0;
|
||||
|
||||
if (options.stdio[i].flags & UV_READABLE_PIPE) {
|
||||
server_access |= PIPE_ACCESS_OUTBOUND;
|
||||
child_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
if (options.stdio[i].flags & UV_WRITABLE_PIPE) {
|
||||
server_access |= PIPE_ACCESS_INBOUND;
|
||||
child_access |= GENERIC_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
err = uv_create_stdio_pipe_pair(
|
||||
loop,
|
||||
pipe,
|
||||
&child_stdio[i],
|
||||
server_access,
|
||||
child_access,
|
||||
overlapped);
|
||||
} else {
|
||||
err = duplicate_handle(loop, pipe->handle, &child_stdio[i]);
|
||||
}
|
||||
} else if(options.stdio[i].data.stream->type == UV_TTY) {
|
||||
err = duplicate_handle(loop,
|
||||
((uv_tty_t*)options.stdio[i].data.stream)->handle, &child_stdio[i]);
|
||||
} else {
|
||||
err = -1;
|
||||
uv__set_artificial_error(loop, UV_ENOTSUP);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
goto done;
|
||||
}
|
||||
if (init_child_stdio(loop, &options, &process->child_stdio_buffer) < 0) {
|
||||
err = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
startup.cb = sizeof(startup);
|
||||
@ -1003,18 +1173,23 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
||||
startup.lpDesktop = NULL;
|
||||
startup.lpTitle = NULL;
|
||||
startup.dwFlags = STARTF_USESTDHANDLES;
|
||||
startup.cbReserved2 = 0;
|
||||
startup.lpReserved2 = NULL;
|
||||
startup.hStdInput = child_stdio[0];
|
||||
startup.hStdOutput = child_stdio[1];
|
||||
startup.hStdError = child_stdio[2];
|
||||
startup.cbReserved2 = CHILD_STDIO_CBRESERVED2(process->child_stdio_buffer);
|
||||
startup.lpReserved2 = CHILD_STDIO_LPRESERVED2(process->child_stdio_buffer);
|
||||
startup.hStdInput = CHILD_STDIO_HANDLE(process->child_stdio_buffer, 0);
|
||||
startup.hStdOutput = CHILD_STDIO_HANDLE(process->child_stdio_buffer, 1);
|
||||
startup.hStdError = CHILD_STDIO_HANDLE(process->child_stdio_buffer, 2);
|
||||
|
||||
process_flags = CREATE_UNICODE_ENVIRONMENT;
|
||||
if (options.flags & UV_PROCESS_DETACHED) {
|
||||
process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
|
||||
}
|
||||
|
||||
if (CreateProcessW(application_path,
|
||||
arguments,
|
||||
NULL,
|
||||
NULL,
|
||||
1,
|
||||
CREATE_UNICODE_ENVIRONMENT,
|
||||
process_flags,
|
||||
env,
|
||||
cwd,
|
||||
&startup,
|
||||
@ -1062,19 +1237,19 @@ done:
|
||||
free(env);
|
||||
free(path);
|
||||
|
||||
/* Under normal circumstances we should close the stdio handles now - */
|
||||
/* the child now has its own duplicates, or something went horribly wrong. */
|
||||
/* Under normal circumstances we should close the stdio handles now - the */
|
||||
/* the child now has its own duplicates, or something went horribly wrong */
|
||||
/* The only exception is when CreateProcess has failed, then we actually */
|
||||
/* need to keep the stdio handles to report the error asynchronously. */
|
||||
if (!keep_child_stdio_open) {
|
||||
close_child_stdio(process);
|
||||
if (process->child_stdio_buffer == NULL) {
|
||||
/* Something went wrong before child stdio was initialized. */
|
||||
} else if (!keep_child_stdio_open) {
|
||||
close_and_free_child_stdio(process->child_stdio_buffer);
|
||||
process->child_stdio_buffer = NULL;
|
||||
} else {
|
||||
/* We're keeping the handles open, the thread pool is going to have */
|
||||
/* it's way with them. But at least make them non-inheritable. */
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(process->child_stdio); i++) {
|
||||
SetHandleInformation(child_stdio[i], HANDLE_FLAG_INHERIT, 0);
|
||||
}
|
||||
set_child_stdio_noinherit(process->child_stdio_buffer);
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
|
6
deps/uv/src/win/tcp.c
vendored
6
deps/uv/src/win/tcp.c
vendored
@ -197,7 +197,6 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
|
||||
if (handle->flags & UV_HANDLE_CLOSING &&
|
||||
handle->reqs_pending == 0) {
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||
handle->flags |= UV_HANDLE_CLOSED;
|
||||
uv__handle_stop(handle);
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_TCP_SOCKET_CLOSED)) {
|
||||
@ -236,10 +235,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
|
||||
}
|
||||
}
|
||||
|
||||
if (handle->close_cb) {
|
||||
handle->close_cb((uv_handle_t*)handle);
|
||||
}
|
||||
|
||||
uv__handle_close(handle);
|
||||
loop->active_tcp_streams--;
|
||||
}
|
||||
}
|
||||
|
6
deps/uv/src/win/timer.c
vendored
6
deps/uv/src/win/timer.c
vendored
@ -126,12 +126,8 @@ int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
|
||||
void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle) {
|
||||
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||
handle->flags |= UV_HANDLE_CLOSED;
|
||||
uv__handle_stop(handle);
|
||||
|
||||
if (handle->close_cb) {
|
||||
handle->close_cb((uv_handle_t*)handle);
|
||||
}
|
||||
uv__handle_close(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
6
deps/uv/src/win/tty.c
vendored
6
deps/uv/src/win/tty.c
vendored
@ -1773,12 +1773,8 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
|
||||
assert(handle->read_raw_wait == NULL);
|
||||
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||
handle->flags |= UV_HANDLE_CLOSED;
|
||||
uv__handle_stop(handle);
|
||||
|
||||
if (handle->close_cb) {
|
||||
handle->close_cb((uv_handle_t*)handle);
|
||||
}
|
||||
uv__handle_close(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
6
deps/uv/src/win/udp.c
vendored
6
deps/uv/src/win/udp.c
vendored
@ -155,12 +155,8 @@ void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) {
|
||||
if (handle->flags & UV_HANDLE_CLOSING &&
|
||||
handle->reqs_pending == 0) {
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||
handle->flags |= UV_HANDLE_CLOSED;
|
||||
uv__handle_stop(handle);
|
||||
|
||||
if (handle->close_cb) {
|
||||
handle->close_cb((uv_handle_t*)handle);
|
||||
}
|
||||
uv__handle_close(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
2
deps/uv/test/benchmark-list.h
vendored
2
deps/uv/test/benchmark-list.h
vendored
@ -21,6 +21,7 @@
|
||||
|
||||
BENCHMARK_DECLARE (sizes)
|
||||
BENCHMARK_DECLARE (loop_count)
|
||||
BENCHMARK_DECLARE (loop_count_timed)
|
||||
BENCHMARK_DECLARE (ping_pongs)
|
||||
BENCHMARK_DECLARE (tcp_write_batch)
|
||||
BENCHMARK_DECLARE (tcp4_pound_100)
|
||||
@ -55,6 +56,7 @@ HELPER_DECLARE (dns_server)
|
||||
TASK_LIST_START
|
||||
BENCHMARK_ENTRY (sizes)
|
||||
BENCHMARK_ENTRY (loop_count)
|
||||
BENCHMARK_ENTRY (loop_count_timed)
|
||||
|
||||
BENCHMARK_ENTRY (ping_pongs)
|
||||
BENCHMARK_HELPER (ping_pongs, tcp4_echo_server)
|
||||
|
36
deps/uv/test/benchmark-loop-count.c
vendored
36
deps/uv/test/benchmark-loop-count.c
vendored
@ -25,12 +25,20 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define NUM_TICKS (2 * 1000 * 1000)
|
||||
|
||||
static unsigned long ticks;
|
||||
static uv_idle_t idle_handle;
|
||||
static uv_timer_t timer_handle;
|
||||
|
||||
|
||||
static void idle_cb(uv_idle_t* handle, int status) {
|
||||
if (++ticks == NUM_TICKS)
|
||||
uv_idle_stop(handle);
|
||||
}
|
||||
|
||||
|
||||
static void idle2_cb(uv_idle_t* handle, int status) {
|
||||
ticks++;
|
||||
}
|
||||
|
||||
@ -43,13 +51,35 @@ static void timer_cb(uv_timer_t* handle, int status) {
|
||||
|
||||
BENCHMARK_IMPL(loop_count) {
|
||||
uv_loop_t* loop = uv_default_loop();
|
||||
|
||||
uv_timer_init(loop, &timer_handle);
|
||||
uv_timer_start(&timer_handle, timer_cb, 5000, 0);
|
||||
uint64_t ns;
|
||||
|
||||
uv_idle_init(loop, &idle_handle);
|
||||
uv_idle_start(&idle_handle, idle_cb);
|
||||
|
||||
ns = uv_hrtime();
|
||||
uv_run(loop);
|
||||
ns = uv_hrtime() - ns;
|
||||
|
||||
ASSERT(ticks == NUM_TICKS);
|
||||
|
||||
LOGF("loop_count: %d ticks in %.2fs (%.0f/s)\n",
|
||||
NUM_TICKS,
|
||||
ns / 1e9,
|
||||
NUM_TICKS / (ns / 1e9));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_IMPL(loop_count_timed) {
|
||||
uv_loop_t* loop = uv_default_loop();
|
||||
|
||||
uv_idle_init(loop, &idle_handle);
|
||||
uv_idle_start(&idle_handle, idle2_cb);
|
||||
|
||||
uv_timer_init(loop, &timer_handle);
|
||||
uv_timer_start(&timer_handle, timer_cb, 5000, 0);
|
||||
|
||||
uv_run(loop);
|
||||
|
||||
LOGF("loop_count: %lu ticks (%.0f ticks/s)\n", ticks, ticks / 5.0);
|
||||
|
16
deps/uv/test/run-tests.c
vendored
16
deps/uv/test/run-tests.c
vendored
@ -22,6 +22,10 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#include "uv.h"
|
||||
#include "runner.h"
|
||||
#include "task.h"
|
||||
@ -104,5 +108,17 @@ static int maybe_run_test(int argc, char **argv) {
|
||||
while (1) uv_sleep(10000);
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "spawn_helper5") == 0) {
|
||||
const char* out = "fourth stdio!\n\0";
|
||||
#ifdef _WIN32
|
||||
DWORD bytes;
|
||||
WriteFile((HANDLE) _get_osfhandle(3), out, strlen(out), &bytes, NULL);
|
||||
#else
|
||||
write(3, out, strlen(out));
|
||||
fsync(3);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
return run_test(argv[1], TEST_TIMEOUT, 0);
|
||||
}
|
||||
|
6
deps/uv/test/test-list.h
vendored
6
deps/uv/test/test-list.h
vendored
@ -81,6 +81,7 @@ TEST_DECLARE (timer_start_twice)
|
||||
TEST_DECLARE (idle_starvation)
|
||||
TEST_DECLARE (loop_handles)
|
||||
TEST_DECLARE (get_loadavg)
|
||||
TEST_DECLARE (walk_handles)
|
||||
TEST_DECLARE (ref)
|
||||
TEST_DECLARE (idle_ref)
|
||||
TEST_DECLARE (async_ref)
|
||||
@ -118,7 +119,9 @@ TEST_DECLARE (pass_always)
|
||||
TEST_DECLARE (spawn_exit_code)
|
||||
TEST_DECLARE (spawn_stdout)
|
||||
TEST_DECLARE (spawn_stdin)
|
||||
TEST_DECLARE (spawn_stdio_greater_than_3)
|
||||
TEST_DECLARE (spawn_and_kill)
|
||||
TEST_DECLARE (spawn_detached)
|
||||
TEST_DECLARE (spawn_and_kill_with_std)
|
||||
TEST_DECLARE (spawn_and_ping)
|
||||
TEST_DECLARE (spawn_setuid_fails)
|
||||
@ -300,6 +303,7 @@ TASK_LIST_START
|
||||
TEST_ENTRY (process_ref)
|
||||
|
||||
TEST_ENTRY (loop_handles)
|
||||
TEST_ENTRY (walk_handles)
|
||||
|
||||
TEST_ENTRY (async)
|
||||
|
||||
@ -330,7 +334,9 @@ TASK_LIST_START
|
||||
TEST_ENTRY (spawn_exit_code)
|
||||
TEST_ENTRY (spawn_stdout)
|
||||
TEST_ENTRY (spawn_stdin)
|
||||
TEST_ENTRY (spawn_stdio_greater_than_3)
|
||||
TEST_ENTRY (spawn_and_kill)
|
||||
TEST_ENTRY (spawn_detached)
|
||||
TEST_ENTRY (spawn_and_kill_with_std)
|
||||
TEST_ENTRY (spawn_and_ping)
|
||||
TEST_ENTRY (spawn_setuid_fails)
|
||||
|
19
deps/uv/test/test-loop-handles.c
vendored
19
deps/uv/test/test-loop-handles.c
vendored
@ -148,7 +148,7 @@ static void idle_1_cb(uv_idle_t* handle, int status) {
|
||||
ASSERT(idles_1_active > 0);
|
||||
|
||||
/* Init idle_2 and make it active */
|
||||
if (!idle_2_is_active) {
|
||||
if (!idle_2_is_active && !uv_is_closing((uv_handle_t*)&idle_2_handle)) {
|
||||
r = uv_idle_init(uv_default_loop(), &idle_2_handle);
|
||||
ASSERT(r == 0);
|
||||
r = uv_idle_start(&idle_2_handle, idle_2_cb);
|
||||
@ -208,11 +208,6 @@ static void check_cb(uv_check_t* handle, int status) {
|
||||
ASSERT(handle == &check_handle);
|
||||
ASSERT(status == 0);
|
||||
|
||||
/* XXX
|
||||
ASSERT(idles_1_active == 0);
|
||||
ASSERT(idle_2_is_active == 0);
|
||||
*/
|
||||
|
||||
if (loop_iteration < ITERATIONS) {
|
||||
/* Make some idle watchers active */
|
||||
for (i = 0; i < 1 + (loop_iteration % IDLE_COUNT); i++) {
|
||||
@ -250,9 +245,6 @@ static void prepare_2_cb(uv_prepare_t* handle, int status) {
|
||||
ASSERT(handle == &prepare_2_handle);
|
||||
ASSERT(status == 0);
|
||||
|
||||
/* XXX ASSERT(idles_1_active == 0); */
|
||||
/* XXX ASSERT(idle_2_is_active == 0); */
|
||||
|
||||
/* prepare_2 gets started by prepare_1 when (loop_iteration % 2 == 0), */
|
||||
/* and it stops itself immediately. A started watcher is not queued */
|
||||
/* until the next round, so when this callback is made */
|
||||
@ -274,11 +266,6 @@ static void prepare_1_cb(uv_prepare_t* handle, int status) {
|
||||
ASSERT(handle == &prepare_1_handle);
|
||||
ASSERT(status == 0);
|
||||
|
||||
/* XXX
|
||||
ASSERT(idles_1_active == 0);
|
||||
ASSERT(idle_2_is_active == 0);
|
||||
*/
|
||||
|
||||
if (loop_iteration % 2 == 0) {
|
||||
r = uv_prepare_start(&prepare_2_handle, prepare_2_cb);
|
||||
ASSERT(r == 0);
|
||||
@ -340,12 +327,8 @@ TEST_IMPL(loop_handles) {
|
||||
ASSERT(check_close_cb_called == 1);
|
||||
|
||||
/* idle_1_cb should be called a lot */
|
||||
/* XXX ASSERT(idle_1_cb_called >= ITERATIONS * IDLE_COUNT * 2); */
|
||||
ASSERT(idle_1_close_cb_called == IDLE_COUNT);
|
||||
/* XXX ASSERT(idles_1_active == 0); */
|
||||
|
||||
/* XXX ASSERT(idle_2_cb_started >= ITERATIONS); */
|
||||
/* XXX ASSERT(idle_2_cb_called == idle_2_cb_started); */
|
||||
ASSERT(idle_2_close_cb_called == idle_2_cb_started);
|
||||
ASSERT(idle_2_is_active == 0);
|
||||
|
||||
|
66
deps/uv/test/test-spawn.c
vendored
66
deps/uv/test/test-spawn.c
vendored
@ -99,6 +99,10 @@ static void kill_cb(uv_process_t* process, int exit_status, int term_signal) {
|
||||
ASSERT(err.code == UV_ESRCH);
|
||||
}
|
||||
|
||||
static void detach_failure_cb(uv_process_t* process, int exit_status, int term_signal) {
|
||||
printf("detach_cb\n");
|
||||
exit_cb_called++;
|
||||
}
|
||||
|
||||
static uv_buf_t on_alloc(uv_handle_t* handle, size_t suggested_size) {
|
||||
uv_buf_t buf;
|
||||
@ -217,7 +221,7 @@ TEST_IMPL(spawn_stdout_to_file) {
|
||||
|
||||
options.stdio = stdio;
|
||||
options.stdio[0].flags = UV_IGNORE;
|
||||
options.stdio[1].flags = UV_RAW_FD;
|
||||
options.stdio[1].flags = UV_INHERIT_FD;
|
||||
options.stdio[1].data.fd = file;
|
||||
options.stdio_count = 2;
|
||||
|
||||
@ -291,6 +295,40 @@ TEST_IMPL(spawn_stdin) {
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(spawn_stdio_greater_than_3) {
|
||||
int r;
|
||||
uv_pipe_t pipe;
|
||||
uv_stdio_container_t stdio[4];
|
||||
|
||||
init_process_options("spawn_helper5", exit_cb);
|
||||
|
||||
uv_pipe_init(uv_default_loop(), &pipe, 0);
|
||||
options.stdio = stdio;
|
||||
options.stdio[0].flags = UV_IGNORE;
|
||||
options.stdio[1].flags = UV_IGNORE;
|
||||
options.stdio[2].flags = UV_IGNORE;
|
||||
options.stdio[3].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
|
||||
options.stdio[3].data.stream = (uv_stream_t*)&pipe;
|
||||
options.stdio_count = 4;
|
||||
|
||||
r = uv_spawn(uv_default_loop(), &process, options);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_read_start((uv_stream_t*) &pipe, on_alloc, on_read);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_run(uv_default_loop());
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(exit_cb_called == 1);
|
||||
ASSERT(close_cb_called == 2); /* Once for process once for the pipe. */
|
||||
printf("output from stdio[3] is: %s", output);
|
||||
ASSERT(strcmp("fourth stdio!\n", output) == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(spawn_and_kill) {
|
||||
int r;
|
||||
|
||||
@ -314,6 +352,32 @@ TEST_IMPL(spawn_and_kill) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(spawn_detached) {
|
||||
int r;
|
||||
uv_err_t err;
|
||||
|
||||
init_process_options("spawn_helper4", detach_failure_cb);
|
||||
|
||||
options.flags |= UV_PROCESS_DETACHED;
|
||||
|
||||
r = uv_spawn(uv_default_loop(), &process, options);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_unref((uv_handle_t*)&process);
|
||||
|
||||
r = uv_run(uv_default_loop());
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(exit_cb_called == 0);
|
||||
|
||||
err = uv_kill(process.pid, 0);
|
||||
ASSERT(err.code == 0);
|
||||
|
||||
err = uv_kill(process.pid, 15);
|
||||
ASSERT(err.code == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(spawn_and_kill_with_std) {
|
||||
int r;
|
||||
|
77
deps/uv/test/test-walk-handles.c
vendored
Normal file
77
deps/uv/test/test-walk-handles.c
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static char magic_cookie[] = "magic cookie";
|
||||
static int seen_timer_handle;
|
||||
static uv_timer_t timer;
|
||||
|
||||
|
||||
static void walk_cb(uv_handle_t* handle, void* arg) {
|
||||
ASSERT(arg == (void*)magic_cookie);
|
||||
|
||||
if (handle == (uv_handle_t*)&timer) {
|
||||
seen_timer_handle++;
|
||||
} else {
|
||||
ASSERT(0 && "unexpected handle");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void timer_cb(uv_timer_t* handle, int status) {
|
||||
ASSERT(handle == &timer);
|
||||
ASSERT(status == 0);
|
||||
|
||||
uv_walk(handle->loop, walk_cb, magic_cookie);
|
||||
uv_close((uv_handle_t*)handle, NULL);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(walk_handles) {
|
||||
uv_loop_t* loop;
|
||||
int r;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
r = uv_timer_init(loop, &timer);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_timer_start(&timer, timer_cb, 1, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
/* Start event loop, expect to see the timer handle in walk_cb. */
|
||||
ASSERT(seen_timer_handle == 0);
|
||||
r = uv_run(loop);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(seen_timer_handle == 1);
|
||||
|
||||
/* Loop is finished, walk_cb should not see our timer handle. */
|
||||
seen_timer_handle = 0;
|
||||
uv_walk(loop, walk_cb, magic_cookie);
|
||||
ASSERT(seen_timer_handle == 0);
|
||||
|
||||
return 0;
|
||||
}
|
1
deps/uv/uv.gyp
vendored
1
deps/uv/uv.gyp
vendored
@ -319,6 +319,7 @@
|
||||
'test/test-ipc-send-recv.c',
|
||||
'test/test-list.h',
|
||||
'test/test-loop-handles.c',
|
||||
'test/test-walk-handles.c',
|
||||
'test/test-multiple-listen.c',
|
||||
'test/test-pass-always.c',
|
||||
'test/test-ping-pong.c',
|
||||
|
Loading…
x
Reference in New Issue
Block a user