unix, windows: rework reference counting scheme

This commit changes how the event loop determines if it needs to stay alive.

Previously, an internal counter was increased whenever a handle got created
and decreased again when the handle was closed.

While conceptually simple, it turned out hard to work with: you often want
to keep the event loop alive only if the handle is actually doing something.
Stopped or inactive handles were a frequent source of hanging event loops.

That's why this commit changes the reference counting scheme to a model where
a handle only references the event loop when it's active. 'Active' means
different things for different handle types, e.g.:

 * timers: ticking
 * sockets: reading, writing or listening
 * processes: always active (for now, subject to change)
 * idle, check, prepare: only active when started

This commit also changes how the uv_ref() and uv_unref() functions work: they
now operate on the level of individual handles, not the whole event loop.

The Windows implementation was done by Bert Belder.
This commit is contained in:
Ben Noordhuis 2012-05-17 06:28:46 +02:00
parent 07622e767d
commit 9efa8b3571
60 changed files with 1004 additions and 968 deletions

View File

@ -29,16 +29,13 @@ CPPFLAGS += -D_FILE_OFFSET_BITS=64
OBJS += src/unix/async.o
OBJS += src/unix/cares.o
OBJS += src/unix/check.o
OBJS += src/unix/core.o
OBJS += src/unix/dl.o
OBJS += src/unix/error.o
OBJS += src/unix/fs.o
OBJS += src/unix/idle.o
OBJS += src/unix/loop.o
OBJS += src/unix/pipe.o
OBJS += src/unix/poll.o
OBJS += src/unix/prepare.o
OBJS += src/unix/process.o
OBJS += src/unix/stream.o
OBJS += src/unix/tcp.o

View File

@ -104,7 +104,10 @@ typedef struct {
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* endgame_handles; \
uv_handle_t* pending_handles; \
ngx_queue_t prepare_handles; \
ngx_queue_t check_handles; \
ngx_queue_t idle_handles; \
UV_LOOP_PRIVATE_PLATFORM_FIELDS
#define UV_REQ_BUFSML_SIZE (4)
@ -141,7 +144,7 @@ typedef struct {
#define UV_HANDLE_PRIVATE_FIELDS \
int fd; \
int flags; \
uv_handle_t* endgame_next; /* that's what uv-win calls it */ \
uv_handle_t* next_pending; \
#define UV_STREAM_PRIVATE_FIELDS \
@ -183,20 +186,20 @@ typedef struct {
/* UV_PREPARE */ \
#define UV_PREPARE_PRIVATE_FIELDS \
ev_prepare prepare_watcher; \
uv_prepare_cb prepare_cb;
uv_prepare_cb prepare_cb; \
ngx_queue_t queue;
/* UV_CHECK */
#define UV_CHECK_PRIVATE_FIELDS \
ev_check check_watcher; \
uv_check_cb check_cb;
uv_check_cb check_cb; \
ngx_queue_t queue;
/* UV_IDLE */
#define UV_IDLE_PRIVATE_FIELDS \
ev_idle idle_watcher; \
uv_idle_cb idle_cb;
uv_idle_cb idle_cb; \
ngx_queue_t queue;
/* UV_ASYNC */

View File

@ -32,6 +32,7 @@
#include <sys/stat.h>
#include "tree.h"
#include "ngx-queue.h"
#define MAX_PIPENAME_LEN 256
@ -203,8 +204,6 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
#define UV_LOOP_PRIVATE_FIELDS \
/* The loop's I/O completion port */ \
HANDLE iocp; \
/* Reference count that keeps the event loop alive */ \
int refs; \
/* The current time according to the event loop. in msecs. */ \
int64_t time; \
/* Tail of a single-linked circular queue of pending reqs. If the queue */ \
@ -246,7 +245,6 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
UV_ARES_EVENT_REQ, \
UV_ARES_CLEANUP_REQ, \
UV_FS_EVENT_REQ, \
UV_GETADDRINFO_REQ, \
UV_POLL_REQ, \
UV_PROCESS_EXIT, \
UV_PROCESS_CLOSE, \
@ -310,6 +308,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
#define UV_STREAM_PRIVATE_FIELDS \
unsigned int reqs_pending; \
int activecnt; \
uv_read_t read_req; \
union { \
struct { uv_stream_connection_fields }; \
@ -337,6 +336,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
#define UV_UDP_PRIVATE_FIELDS \
SOCKET socket; \
unsigned int reqs_pending; \
int activecnt; \
uv_req_t recv_req; \
uv_buf_t recv_buffer; \
struct sockaddr_storage recv_from; \
@ -444,7 +444,6 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
unsigned int flags;
#define UV_GETADDRINFO_PRIVATE_FIELDS \
struct uv_req_s getadddrinfo_req; \
uv_getaddrinfo_cb getaddrinfo_cb; \
void* alloc; \
wchar_t* node; \

View File

@ -224,10 +224,6 @@ typedef struct uv_work_s uv_work_t;
UV_EXTERN uv_loop_t* uv_loop_new(void);
UV_EXTERN void uv_loop_delete(uv_loop_t*);
/* This is a debugging tool. It's NOT part of the official API. */
UV_EXTERN int uv_loop_refcount(const uv_loop_t*);
/*
* Returns the default loop.
*/
@ -248,8 +244,8 @@ UV_EXTERN int uv_run_once (uv_loop_t*);
* Manually modify the event loop's reference count. Useful if the user wants
* to have a handle or timeout that doesn't keep the loop alive.
*/
UV_EXTERN void uv_ref(uv_loop_t*);
UV_EXTERN void uv_unref(uv_loop_t*);
UV_EXTERN void uv_ref(uv_handle_t*);
UV_EXTERN void uv_unref(uv_handle_t*);
UV_EXTERN void uv_update_time(uv_loop_t*);
UV_EXTERN int64_t uv_now(uv_loop_t*);
@ -336,12 +332,18 @@ UV_EXTERN uv_err_t uv_last_error(uv_loop_t*);
UV_EXTERN const char* uv_strerror(uv_err_t err);
UV_EXTERN const char* uv_err_name(uv_err_t err);
#ifndef UV_LEAN_AND_MEAN
# define UV_REQ_EXTRA_FIELDS ngx_queue_t active_queue;
#else
# define UV_REQ_EXTRA_FIELDS
#endif
#define UV_REQ_FIELDS \
/* read-only */ \
uv_req_type type; \
/* public */ \
void* data; \
UV_REQ_EXTRA_FIELDS \
/* private */ \
UV_REQ_PRIVATE_FIELDS
@ -374,6 +376,12 @@ struct uv_shutdown_s {
};
#ifndef UV_LEAN_AND_MEAN
# define UV_HANDLE_EXTRA_FIELDS ngx_queue_t active_queue;
#else
# define UV_HANDLE_EXTRA_FIELDS
#endif
#define UV_HANDLE_FIELDS \
/* read-only */ \
uv_loop_t* loop; \
@ -381,6 +389,7 @@ struct uv_shutdown_s {
/* public */ \
uv_close_cb close_cb; \
void* data; \
UV_HANDLE_EXTRA_FIELDS \
/* private */ \
UV_HANDLE_PRIVATE_FIELDS
@ -1638,6 +1647,13 @@ struct uv_loop_s {
uv_err_t last_err;
/* User data - use this for whatever. */
void* data;
#ifndef UV_LEAN_AND_MEAN
ngx_queue_t active_reqs;
ngx_queue_t active_handles;
#else
unsigned int active_reqs;
unsigned int active_handles;
#endif
};

View File

@ -40,7 +40,8 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* async, uv_async_cb async_cb) {
/* Note: This does not have symmetry with the other libev wrappers. */
ev_async_start(loop->ev, &async->async_watcher);
ev_unref(loop->ev);
uv__handle_unref(async);
uv__handle_start(async);
return 0;
}
@ -54,5 +55,6 @@ int uv_async_send(uv_async_t* async) {
void uv__async_close(uv_async_t* handle) {
ev_async_stop(handle->loop->ev, &handle->async_watcher);
ev_ref(handle->loop->ev);
uv__handle_ref(handle);
uv__handle_stop(handle);
}

View File

@ -37,20 +37,6 @@ static void uv__ares_timeout(uv_timer_t* handle, int status) {
}
static void uv__ares_timer_start(uv_loop_t* loop) {
if (uv_is_active((uv_handle_t*)&loop->timer)) return;
uv_timer_start(&loop->timer, uv__ares_timeout, 1000, 1000);
uv_ref(loop);
}
static void uv__ares_timer_stop(uv_loop_t* loop) {
if (!uv_is_active((uv_handle_t*)&loop->timer)) return;
uv_timer_stop(&loop->timer);
uv_unref(loop);
}
static void uv__ares_io(struct ev_loop* ev, struct ev_io* watcher,
int revents) {
uv_loop_t* loop = ev_userdata(ev);
@ -104,9 +90,9 @@ static void uv__ares_sockstate_cb(void* data, ares_socket_t sock,
/* New socket */
/* If this is the first socket then start the timer. */
if (!uv_is_active((uv_handle_t*)&loop->timer)) {
if (!uv__is_active(&loop->timer)) {
assert(uv_ares_handles_empty(loop));
uv__ares_timer_start(loop);
uv_timer_start(&loop->timer, uv__ares_timeout, 1000, 1000);
}
h = uv__ares_task_create(loop, sock);
@ -140,7 +126,7 @@ static void uv__ares_sockstate_cb(void* data, ares_socket_t sock,
free(h);
if (uv_ares_handles_empty(loop)) {
uv__ares_timer_stop(loop);
uv_timer_stop(&loop->timer);
}
}
}
@ -176,7 +162,6 @@ int uv_ares_init_options(uv_loop_t* loop, ares_channel *channelptr,
* first socket is opened.
*/
uv_timer_init(loop, &loop->timer);
uv_unref(loop);
loop->timer.data = loop;
return rc;
@ -187,7 +172,7 @@ int uv_ares_init_options(uv_loop_t* loop, ares_channel *channelptr,
void uv_ares_destroy(uv_loop_t* loop, ares_channel channel) {
/* only allow destroy if did init */
if (loop->channel) {
uv__ares_timer_stop(loop);
uv_timer_stop(&loop->timer);
ares_destroy(channel);
loop->channel = NULL;
}

View File

@ -1,80 +0,0 @@
/* 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 "internal.h"
static void uv__check(EV_P_ ev_check* w, int revents) {
uv_check_t* check = container_of(w, uv_check_t, check_watcher);
if (check->check_cb) {
check->check_cb(check, 0);
}
}
int uv_check_init(uv_loop_t* loop, uv_check_t* check) {
uv__handle_init(loop, (uv_handle_t*)check, UV_CHECK);
loop->counters.check_init++;
ev_check_init(&check->check_watcher, uv__check);
check->check_cb = NULL;
return 0;
}
int uv_check_start(uv_check_t* check, uv_check_cb cb) {
int was_active = ev_is_active(&check->check_watcher);
check->check_cb = cb;
ev_check_start(check->loop->ev, &check->check_watcher);
if (!was_active) {
ev_unref(check->loop->ev);
}
return 0;
}
int uv_check_stop(uv_check_t* check) {
int was_active = ev_is_active(&check->check_watcher);
ev_check_stop(check->loop->ev, &check->check_watcher);
if (was_active) {
ev_ref(check->loop->ev);
}
return 0;
}
int uv__check_active(const uv_check_t* handle) {
return ev_is_active(&handle->check_watcher);
}
void uv__check_close(uv_check_t* handle) {
uv_check_stop(handle);
}

View File

@ -19,7 +19,7 @@
*/
#include "uv.h"
#include "unix/internal.h"
#include "internal.h"
#include <stddef.h> /* NULL */
#include <stdio.h> /* printf */
@ -116,9 +116,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
}
handle->flags |= UV_CLOSING;
handle->endgame_next = handle->loop->endgame_handles;
handle->loop->endgame_handles = handle;
uv_unref(handle->loop);
uv__make_pending(handle);
}
@ -165,24 +163,66 @@ void uv_loop_delete(uv_loop_t* loop) {
}
int uv_loop_refcount(const uv_loop_t* loop) {
return ev_loop_refcount(loop->ev);
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();
}
}
}
void uv__run(uv_loop_t* loop) {
ev_run(loop->ev, EVRUN_ONCE);
static void uv__poll(uv_loop_t* loop, int block) {
/* 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_unref(loop->ev);
}
while (loop->endgame_handles)
uv__finish_close(loop->endgame_handles);
static int uv__run(uv_loop_t* loop) {
if (!uv__has_pending_handles(loop) && !uv__has_active_reqs(loop))
uv__run_idle(loop);
uv__run_pending(loop);
uv__run_prepare(loop);
if (uv__has_active_handles(loop) || uv__has_active_reqs(loop))
uv__poll(loop, 0);
uv__run_check(loop);
return uv__has_pending_handles(loop)
|| uv__has_active_handles(loop)
|| uv__has_active_reqs(loop);
}
int uv_run(uv_loop_t* loop) {
do
uv__run(loop);
while (uv_loop_refcount(loop) > 0);
while (uv__run(loop));
return 0;
}
@ -199,38 +239,24 @@ void uv__handle_init(uv_loop_t* loop, uv_handle_t* handle,
handle->loop = loop;
handle->type = type;
handle->flags = 0;
handle->endgame_next = NULL;
uv_ref(loop); /* unref'd in uv_close() */
handle->flags = UV__REF; /* ref the loop when active */
handle->next_pending = NULL;
}
void uv__finish_close(uv_handle_t* handle) {
uv_loop_t* loop = handle->loop;
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:
assert(!ev_is_active(&((uv_prepare_t*)handle)->prepare_watcher));
break;
case UV_CHECK:
assert(!ev_is_active(&((uv_check_t*)handle)->check_watcher));
break;
case UV_IDLE:
assert(!ev_is_active(&((uv_idle_t*)handle)->idle_watcher));
break;
case UV_ASYNC:
assert(!ev_is_active(&((uv_async_t*)handle)->async_watcher));
break;
case UV_TIMER:
assert(!ev_is_active(&((uv_timer_t*)handle)->timer_watcher));
case UV_PROCESS:
break;
case UV_NAMED_PIPE:
@ -246,10 +272,6 @@ void uv__finish_close(uv_handle_t* handle) {
uv__udp_finish_close((uv_udp_t*)handle);
break;
case UV_PROCESS:
assert(!ev_is_active(&((uv_process_t*)handle)->child_watcher));
break;
case UV_FS_EVENT:
break;
@ -262,21 +284,11 @@ void uv__finish_close(uv_handle_t* handle) {
}
loop->endgame_handles = handle->endgame_next;
if (handle->close_cb) {
handle->close_cb(handle);
}
}
void uv_ref(uv_loop_t* loop) {
ev_ref(loop->ev);
}
void uv_unref(uv_loop_t* loop) {
ev_unref(loop->ev);
uv__handle_unref(handle);
}
@ -291,56 +303,43 @@ int64_t uv_now(uv_loop_t* loop) {
int uv_is_active(const uv_handle_t* handle) {
switch (handle->type) {
case UV_POLL:
return uv__poll_active((const uv_poll_t*)handle);
case UV_CHECK:
return uv__check_active((const uv_check_t*)handle);
case UV_IDLE:
return uv__idle_active((const uv_idle_t*)handle);
case UV_PREPARE:
return uv__prepare_active((const uv_prepare_t*)handle);
case UV_TIMER:
return uv__timer_active((const uv_timer_t*)handle);
default:
return 1;
}
return uv__is_active(handle);
}
static int uv_getaddrinfo_done(eio_req* req) {
uv_getaddrinfo_t* handle = req->data;
struct addrinfo *res = handle->res;
static int uv_getaddrinfo_done(eio_req* req_) {
uv_getaddrinfo_t* req = req_->data;
struct addrinfo *res = req->res;
#if __sun
size_t hostlen = strlen(handle->hostname);
#endif
handle->res = NULL;
req->res = NULL;
uv_unref(handle->loop);
uv__req_unregister(req->loop, req);
free(handle->hints);
free(handle->service);
free(handle->hostname);
free(req->hints);
free(req->service);
free(req->hostname);
if (handle->retcode == 0) {
if (req->retcode == 0) {
/* OK */
#if EAI_NODATA /* FreeBSD deprecated EAI_NODATA */
} else if (handle->retcode == EAI_NONAME || handle->retcode == EAI_NODATA) {
} else if (req->retcode == EAI_NONAME || req->retcode == EAI_NODATA) {
#else
} else if (handle->retcode == EAI_NONAME) {
} else if (req->retcode == EAI_NONAME) {
#endif
uv__set_sys_error(handle->loop, ENOENT); /* FIXME compatibility hack */
uv__set_sys_error(req->loop, ENOENT); /* FIXME compatibility hack */
#if __sun
} else if (handle->retcode == EAI_MEMORY && hostlen >= MAXHOSTNAMELEN) {
uv__set_sys_error(handle->loop, ENOENT);
} else if (req->retcode == EAI_MEMORY && hostlen >= MAXHOSTNAMELEN) {
uv__set_sys_error(req->loop, ENOENT);
#endif
} else {
handle->loop->last_err.code = UV_EADDRINFO;
handle->loop->last_err.sys_errno_ = handle->retcode;
req->loop->last_err.code = UV_EADDRINFO;
req->loop->last_err.sys_errno_ = req->retcode;
}
handle->cb(handle, handle->retcode, res);
req->cb(req, req->retcode, res);
return 0;
}
@ -396,8 +395,6 @@ int uv_getaddrinfo(uv_loop_t* loop,
/* TODO check handle->hostname == NULL */
/* TODO check handle->service == NULL */
uv_ref(loop);
req = eio_custom(getaddrinfo_thread_proc, EIO_PRI_DEFAULT,
uv_getaddrinfo_done, handle, &loop->uv_eio_channel);
assert(req);
@ -480,7 +477,7 @@ int uv__accept(int sockfd, struct sockaddr* saddr, socklen_t slen) {
int uv__nonblock(int fd, int set) {
#ifdef FIONBIO
#if FIONBIO
return ioctl(fd, FIONBIO, &set);
#else
int flags;

View File

@ -49,7 +49,6 @@
uv__set_sys_error(loop, ENOMEM); \
return -1; \
} \
uv_ref(loop); \
} else { \
/* sync */ \
req->result = func(args); \
@ -75,10 +74,17 @@ static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req, uv_fs_type fs_type,
req->path = path ? strdup(path) : NULL;
req->errorno = 0;
req->eio = NULL;
/* synchronous requests don't increase the reference count */
if (!req->cb)
uv__req_unregister(req->loop, req);
}
void uv_fs_req_cleanup(uv_fs_t* req) {
if (req->cb)
uv__req_unregister(req->loop, req);
free(req->path);
req->path = NULL;
@ -169,10 +175,9 @@ static int uv__fs_after(eio_req* eio) {
break;
}
uv_unref(req->loop);
req->eio = NULL; /* Freed by libeio */
req->cb(req);
return 0;
}
@ -189,7 +194,6 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
if (cb) {
/* async */
uv_ref(loop);
req->eio = eio_open(path, flags, mode, EIO_PRI_DEFAULT, uv__fs_after, req, &loop->uv_eio_channel);
if (!req->eio) {
uv__set_sys_error(loop, ENOMEM);
@ -219,7 +223,6 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file fd, void* buf,
if (cb) {
/* async */
uv_ref(loop);
req->eio = eio_read(fd, buf, length, offset, EIO_PRI_DEFAULT,
uv__fs_after, req, &loop->uv_eio_channel);
@ -257,7 +260,6 @@ int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf,
if (cb) {
/* async */
uv_ref(loop);
req->eio = eio_write(file, buf, length, offset, EIO_PRI_DEFAULT,
uv__fs_after, req, &loop->uv_eio_channel);
if (!req->eio) {
@ -305,7 +307,6 @@ int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
if (cb) {
/* async */
uv_ref(loop);
req->eio = eio_readdir(path, flags, EIO_PRI_DEFAULT, uv__fs_after, req, &loop->uv_eio_channel);
if (!req->eio) {
uv__set_sys_error(loop, ENOMEM);
@ -375,7 +376,6 @@ int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
if (cb) {
/* async */
uv_ref(loop);
req->eio = eio_stat(pathdup, EIO_PRI_DEFAULT, uv__fs_after, req, &loop->uv_eio_channel);
free(pathdup);
@ -409,7 +409,6 @@ int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
if (cb) {
/* async */
uv_ref(loop);
req->eio = eio_fstat(file, EIO_PRI_DEFAULT, uv__fs_after, req, &loop->uv_eio_channel);
if (!req->eio) {
@ -495,7 +494,6 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
}
#if HAVE_FUTIMES
static int _futime(const uv_file fd, double atime, double mtime) {
#if __linux__
/* utimesat() has nanosecond resolution but we stick to microseconds
@ -507,30 +505,24 @@ static int _futime(const uv_file fd, double atime, double mtime) {
ts[1].tv_sec = mtime;
ts[1].tv_nsec = (unsigned long)(mtime * 1000000) % 1000000 * 1000;
return uv__utimesat(fd, NULL, ts, 0);
#else
#elif HAVE_FUTIMES
struct timeval tv[2];
tv[0].tv_sec = atime;
tv[0].tv_usec = (unsigned long)(atime * 1000000) % 1000000;
tv[1].tv_sec = mtime;
tv[1].tv_usec = (unsigned long)(mtime * 1000000) % 1000000;
return futimes(fd, tv);
#endif /* __linux__ */
#else /* !HAVE_FUTIMES */
errno = ENOSYS;
return -1;
#endif
}
#endif /* HAVE_FUTIMES */
int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime,
double mtime, uv_fs_cb cb) {
const char* path = NULL;
uv_fs_req_init(loop, req, UV_FS_FUTIME, path, cb);
#if HAVE_FUTIMES
WRAP_EIO(UV_FS_FUTIME, eio_futime, _futime, ARGS3(file, atime, mtime))
#else
uv__set_sys_error(loop, ENOSYS);
return -1;
#endif
}
@ -552,7 +544,6 @@ int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
if (cb) {
/* async */
uv_ref(loop);
req->eio = eio_lstat(pathdup, EIO_PRI_DEFAULT, uv__fs_after, req, &loop->uv_eio_channel);
free(pathdup);
@ -602,7 +593,6 @@ int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
if (cb) {
if ((req->eio = eio_readlink(path, EIO_PRI_DEFAULT, uv__fs_after, req, &loop->uv_eio_channel))) {
uv_ref(loop);
return 0;
} else {
uv__set_sys_error(loop, ENOMEM);
@ -674,7 +664,7 @@ static void uv__work(eio_req* eio) {
static int uv__after_work(eio_req *eio) {
uv_work_t* req = eio->data;
uv_unref(req->loop);
uv__req_unregister(req->loop, req);
if (req->after_work_cb) {
req->after_work_cb(req);
}
@ -689,13 +679,16 @@ int uv_queue_work(uv_loop_t* loop, uv_work_t* req, uv_work_cb work_cb,
uv_eio_init(loop);
uv__req_init(loop, req, UV_WORK);
uv_ref(loop);
req->loop = loop;
req->data = data;
req->work_cb = work_cb;
req->after_work_cb = after_work_cb;
req->eio = eio_custom(uv__work, EIO_PRI_DEFAULT, uv__after_work, req, &loop->uv_eio_channel);
req->eio = eio_custom(uv__work,
EIO_PRI_DEFAULT,
uv__after_work,
req,
&loop->uv_eio_channel);
if (!req->eio) {
uv__set_sys_error(loop, ENOMEM);

View File

@ -1,79 +0,0 @@
/* 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 "internal.h"
static void uv__idle(EV_P_ ev_idle* w, int revents) {
uv_idle_t* idle = container_of(w, uv_idle_t, idle_watcher);
if (idle->idle_cb) {
idle->idle_cb(idle, 0);
}
}
int uv_idle_init(uv_loop_t* loop, uv_idle_t* idle) {
uv__handle_init(loop, (uv_handle_t*)idle, UV_IDLE);
loop->counters.idle_init++;
ev_idle_init(&idle->idle_watcher, uv__idle);
idle->idle_cb = NULL;
return 0;
}
int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb) {
int was_active = ev_is_active(&idle->idle_watcher);
idle->idle_cb = cb;
ev_idle_start(idle->loop->ev, &idle->idle_watcher);
if (!was_active) {
ev_unref(idle->loop->ev);
}
return 0;
}
int uv_idle_stop(uv_idle_t* idle) {
int was_active = ev_is_active(&idle->idle_watcher);
ev_idle_stop(idle->loop->ev, &idle->idle_watcher);
if (was_active) {
ev_ref(idle->loop->ev);
}
return 0;
}
int uv__idle_active(const uv_idle_t* handle) {
return ev_is_active(&handle->idle_watcher);
}
void uv__idle_close(uv_idle_t* handle) {
uv_idle_stop(handle);
}

View File

@ -93,15 +93,32 @@ enum {
UV_STREAM_WRITABLE = 0x40, /* The stream is writable */
UV_TCP_NODELAY = 0x080, /* Disable Nagle. */
UV_TCP_KEEPALIVE = 0x100, /* Turn on keep-alive. */
UV_TIMER_ACTIVE = 0x080,
UV_TIMER_REPEAT = 0x100
UV_TIMER_REPEAT = 0x100,
UV__PENDING = 0x800
};
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) {
loop->counters.req_init++;
req->type = type;
#ifndef UV_LEAN_AND_MEAN
ngx_queue_insert_tail(&loop->active_reqs, &req->active_queue);
#else
loop->active_reqs++;
#endif
}
#define uv__req_init(loop, req, type) \
uv__req_init((loop), (uv_req_t*)(req), (type))
@ -112,10 +129,14 @@ int uv__nonblock(int fd, int set) __attribute__((unused));
int uv__cloexec(int fd, int set) __attribute__((unused));
int uv__socket(int domain, int type, int protocol);
int uv__dup(int fd);
int uv_async_stop(uv_async_t* handle);
/* loop */
int uv__loop_init(uv_loop_t* loop, int default_loop);
void uv__loop_delete(uv_loop_t* loop);
void uv__run_idle(uv_loop_t* loop);
void uv__run_check(uv_loop_t* loop);
void uv__run_prepare(uv_loop_t* loop);
/* error */
uv_err_code uv_translate_sys_error(int sys_errno);
@ -146,11 +167,6 @@ void uv__poll_close(uv_poll_t* handle);
int uv__poll_active(const uv_poll_t* handle);
/* various */
int uv__check_active(const uv_check_t* handle);
int uv__idle_active(const uv_idle_t* handle);
int uv__prepare_active(const uv_prepare_t* handle);
int uv__timer_active(const uv_timer_t* handle);
void uv__async_close(uv_async_t* handle);
void uv__check_close(uv_check_t* handle);
void uv__fs_event_close(uv_fs_event_t* handle);
@ -163,6 +179,8 @@ 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);

View File

@ -42,12 +42,10 @@ static void uv__fs_event_start(uv_fs_event_t* handle) {
handle->fd,
EV_LIBUV_KQUEUE_HACK);
ev_io_start(handle->loop->ev, &handle->event_watcher);
ev_unref(handle->loop->ev);
}
static void uv__fs_event_stop(uv_fs_event_t* handle) {
ev_ref(handle->loop->ev);
ev_io_stop(handle->loop->ev, &handle->event_watcher);
}
@ -104,6 +102,7 @@ int uv_fs_event_init(uv_loop_t* loop,
}
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
uv__handle_start(handle); /* FIXME shouldn't start automatically */
handle->filename = strdup(filename);
handle->fflags = 0;
handle->cb = cb;
@ -116,6 +115,7 @@ int uv_fs_event_init(uv_loop_t* loop,
void uv__fs_event_close(uv_fs_event_t* handle) {
uv__fs_event_stop(handle);
uv__handle_stop(handle);
free(handle->filename);
close(handle->fd);
handle->fd = -1;

View File

@ -90,7 +90,6 @@ static int init_inotify(uv_loop_t* loop) {
loop->inotify_fd,
EV_READ);
ev_io_start(loop->ev, &loop->inotify_read_watcher);
ev_unref(loop->ev);
return 0;
}
@ -193,6 +192,7 @@ int uv_fs_event_init(uv_loop_t* loop,
if (wd == -1) return uv__set_sys_error(loop, errno);
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
uv__handle_start(handle); /* FIXME shouldn't start automatically */
handle->filename = strdup(filename);
handle->cb = cb;
handle->fd = wd;
@ -209,4 +209,5 @@ void uv__fs_event_close(uv_fs_event_t* handle) {
free(handle->filename);
handle->filename = NULL;
uv__handle_stop(handle);
}

View File

@ -33,13 +33,24 @@ int uv__loop_init(uv_loop_t* loop, int default_loop) {
#else
int flags = EVFLAG_AUTO;
#endif
memset(loop, 0, sizeof(*loop));
#ifndef UV_LEAN_AND_MEAN
ngx_queue_init(&loop->active_handles);
ngx_queue_init(&loop->active_reqs);
#endif
RB_INIT(&loop->uv_ares_handles_);
loop->endgame_handles = NULL;
ngx_queue_init(&loop->idle_handles);
ngx_queue_init(&loop->check_handles);
ngx_queue_init(&loop->prepare_handles);
loop->pending_handles = NULL;
loop->channel = NULL;
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);
#if __linux__
RB_INIT(&loop->inotify_watchers);
loop->inotify_fd = -1;
@ -65,3 +76,40 @@ void uv__loop_delete(uv_loop_t* loop) {
close(loop->fs_fd);
#endif
}
#define X(name, type) \
int uv_##name##_init(uv_loop_t* loop, uv_##name##_t* handle) { \
uv__handle_init(loop, (uv_handle_t*)handle, type); \
loop->counters.name##_init++; \
handle->name##_cb = NULL; \
return 0; \
} \
int uv_##name##_start(uv_##name##_t* handle, uv_##name##_cb cb) { \
if (uv__is_active(handle)) return 0; \
ngx_queue_insert_head(&handle->loop->name##_handles, &handle->queue); \
handle->name##_cb = cb; \
uv__handle_start(handle); \
return 0; \
} \
int uv_##name##_stop(uv_##name##_t* handle) { \
if (!uv__is_active(handle)) return 0; \
ngx_queue_remove(&handle->queue); \
uv__handle_stop(handle); \
return 0; \
} \
void uv__run_##name(uv_loop_t* loop) { \
uv_##name##_t* h; \
ngx_queue_t* q; \
ngx_queue_foreach(q, &loop->name##_handles) { \
h = ngx_queue_data(q, uv_##name##_t, queue); \
if (h->name##_cb) h->name##_cb(h, 0); \
} \
} \
void uv__##name##_close(uv_##name##_t* handle) { \
uv_##name##_stop(handle); \
}
X(idle, UV_IDLE)
X(check, UV_CHECK)
X(prepare, UV_PREPARE)
#undef X

View File

@ -33,6 +33,8 @@
int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);
loop->counters.pipe_init++;
handle->shutdown_req = NULL;
handle->connect_req = NULL;
handle->pipe_fname = NULL;
handle->ipc = ipc;
return 0;
@ -209,23 +211,21 @@ void uv_pipe_connect(uv_connect_t* req,
uv__stream_open((uv_stream_t*)handle,
sockfd,
UV_STREAM_READABLE | UV_STREAM_WRITABLE);
ev_io_start(handle->loop->ev, &handle->read_watcher);
ev_io_start(handle->loop->ev, &handle->write_watcher);
status = 0;
out:
handle->delayed_error = status; /* Passed to callback. */
handle->connect_req = req;
uv__req_init(handle->loop, req, UV_CONNECT);
req->handle = (uv_stream_t*)handle;
req->type = UV_CONNECT;
req->cb = cb;
ngx_queue_init(&req->queue);
/* Run callback on next tick. */
ev_feed_event(handle->loop->ev, &handle->read_watcher, EV_CUSTOM);
assert(ev_is_pending(&handle->read_watcher));
uv__make_pending(handle);
/* Mimic the Windows pipe implementation, always
* return 0 and let the callback handle errors.

View File

@ -34,7 +34,7 @@ static void uv__poll_io(EV_P_ ev_io* watcher, int ev_events) {
if (ev_events & EV_ERROR) {
/* An error happened. Libev has implicitly stopped the watcher, but we */
/* need to fix the refcount. */
uv_ref(handle->loop);
uv__handle_stop(handle);
uv__set_sys_error(handle->loop, EBADF);
handle->poll_cb(handle, -1, 0);
return;
@ -74,10 +74,8 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
static void uv__poll_stop(uv_poll_t* handle) {
if (ev_is_active(&handle->io_watcher)) {
ev_io_stop(handle->loop->ev, &handle->io_watcher);
uv_ref(handle->loop);
}
uv__handle_stop(handle);
}
@ -111,10 +109,8 @@ int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb poll_cb) {
ev_io_set(&handle->io_watcher, handle->fd, ev_events);
ev_io_start(handle->loop->ev, &handle->io_watcher);
if (!was_active)
uv_unref(handle->loop);
handle->poll_cb = poll_cb;
uv__handle_start(handle);
return 0;
}

View File

@ -1,79 +0,0 @@
/* 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 "internal.h"
static void uv__prepare(EV_P_ ev_prepare* w, int revents) {
uv_prepare_t* prepare = container_of(w, uv_prepare_t, prepare_watcher);
if (prepare->prepare_cb) {
prepare->prepare_cb(prepare, 0);
}
}
int uv_prepare_init(uv_loop_t* loop, uv_prepare_t* prepare) {
uv__handle_init(loop, (uv_handle_t*)prepare, UV_PREPARE);
loop->counters.prepare_init++;
ev_prepare_init(&prepare->prepare_watcher, uv__prepare);
prepare->prepare_cb = NULL;
return 0;
}
int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb) {
int was_active = ev_is_active(&prepare->prepare_watcher);
prepare->prepare_cb = cb;
ev_prepare_start(prepare->loop->ev, &prepare->prepare_watcher);
if (!was_active) {
ev_unref(prepare->loop->ev);
}
return 0;
}
int uv_prepare_stop(uv_prepare_t* prepare) {
int was_active = ev_is_active(&prepare->prepare_watcher);
ev_prepare_stop(prepare->loop->ev, &prepare->prepare_watcher);
if (was_active) {
ev_ref(prepare->loop->ev);
}
return 0;
}
int uv__prepare_active(const uv_prepare_t* handle) {
return ev_is_active(&handle->prepare_watcher);
}
void uv__prepare_close(uv_prepare_t* handle) {
uv_prepare_stop(handle);
}

View File

@ -181,6 +181,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
loop->counters.process_init++;
uv__handle_start(process);
process->exit_cb = options.exit_cb;
@ -384,4 +385,5 @@ 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);
uv__handle_stop(handle);
}

View File

@ -123,6 +123,7 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
void uv__stream_destroy(uv_stream_t* stream) {
uv_shutdown_t* shutdown_req;
uv_write_t* req;
ngx_queue_t* q;
@ -133,6 +134,8 @@ void uv__stream_destroy(uv_stream_t* stream) {
ngx_queue_remove(q);
req = ngx_queue_data(q, uv_write_t, queue);
uv__req_unregister(stream->loop, req);
if (req->bufs != req->bufsml)
free(req->bufs);
@ -147,18 +150,27 @@ void uv__stream_destroy(uv_stream_t* stream) {
ngx_queue_remove(q);
req = ngx_queue_data(q, uv_write_t, queue);
uv__req_unregister(stream->loop, req);
if (req->cb) {
uv__set_sys_error(stream->loop, req->error);
req->cb(req, req->error ? -1 : 0);
}
}
if (stream->flags & UV_STREAM_SHUTTING) {
uv_shutdown_t* req = stream->shutdown_req;
if (req && req->cb) {
if (!(stream->flags & UV_STREAM_SHUTTING))
return;
if (!stream->shutdown_req)
return;
shutdown_req = stream->shutdown_req;
stream->shutdown_req = NULL;
uv__req_unregister(stream->loop, shutdown_req);
if (shutdown_req->cb) {
uv__set_artificial_error(stream->loop, UV_EINTR);
req->cb(req, -1);
}
shutdown_req->cb(shutdown_req, -1);
}
}
@ -252,15 +264,26 @@ out:
int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
int r;
switch (stream->type) {
case UV_TCP:
return uv_tcp_listen((uv_tcp_t*)stream, backlog, cb);
r = uv_tcp_listen((uv_tcp_t*)stream, backlog, cb);
break;
case UV_NAMED_PIPE:
return uv_pipe_listen((uv_pipe_t*)stream, backlog, cb);
r = uv_pipe_listen((uv_pipe_t*)stream, backlog, cb);
break;
default:
assert(0);
return -1;
}
if (r == 0)
uv__handle_start(stream);
return r;
}
@ -300,6 +323,7 @@ static void uv__drain(uv_stream_t* stream) {
req = stream->shutdown_req;
stream->shutdown_req = NULL;
uv__req_unregister(stream->loop, req);
if (shutdown(stream->fd, SHUT_WR)) {
/* Error. Report it. User should call uv_close(). */
@ -499,24 +523,21 @@ start:
static void uv__write_callbacks(uv_stream_t* stream) {
int callbacks_made = 0;
ngx_queue_t* q;
uv_write_t* req;
ngx_queue_t* q;
while (!ngx_queue_empty(&stream->write_completed_queue)) {
/* Pop a req off write_completed_queue. */
q = ngx_queue_head(&stream->write_completed_queue);
assert(q);
req = ngx_queue_data(q, struct uv_write_s, queue);
req = ngx_queue_data(q, uv_write_t, queue);
ngx_queue_remove(q);
uv__req_unregister(stream->loop, req);
/* NOTE: call callback AFTER freeing the request data. */
if (req->cb) {
uv__set_sys_error(stream->loop, req->error);
req->cb(req, req->error ? -1 : 0);
}
callbacks_made++;
}
assert(ngx_queue_empty(&stream->write_completed_queue));
@ -628,6 +649,8 @@ static void uv__read(uv_stream_t* stream) {
/* EOF */
uv__set_artificial_error(stream->loop, UV_EOF);
ev_io_stop(ev, &stream->read_watcher);
if (!ev_is_active(&stream->write_watcher))
uv__handle_stop(stream);
if (stream->read_cb) {
stream->read_cb(stream, -1, buf);
@ -704,9 +727,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
req->handle = stream;
req->cb = cb;
stream->shutdown_req = req;
((uv_handle_t*)stream)->flags |= UV_STREAM_SHUTTING;
stream->flags |= UV_STREAM_SHUTTING;
ev_io_start(stream->loop->ev, &stream->write_watcher);
@ -714,6 +735,11 @@ 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->ev, &handle->write_watcher, EV_WRITE);
}
void uv__stream_io(EV_P_ ev_io* watcher, int revents) {
uv_stream_t* stream = watcher->data;
@ -767,26 +793,18 @@ static void uv__stream_connect(uv_stream_t* stream) {
getsockopt(stream->fd, SOL_SOCKET, SO_ERROR, &error, &errorsize);
}
if (!error) {
if (error == EINPROGRESS)
return;
if (error == 0)
ev_io_start(stream->loop->ev, &stream->read_watcher);
/* Successful connection */
stream->connect_req = NULL;
if (req->cb) {
req->cb(req, 0);
}
uv__req_unregister(stream->loop, req);
} else if (error == EINPROGRESS) {
/* Still connecting. */
return;
} else {
/* Error */
if (req->cb) {
uv__set_sys_error(stream->loop, error);
stream->connect_req = NULL;
if (req->cb) {
req->cb(req, -1);
}
req->cb(req, error ? -1 : 0);
}
}
@ -855,9 +873,8 @@ int uv__connect(uv_connect_t* req, uv_stream_t* stream, struct sockaddr* addr,
assert(stream->write_watcher.data == stream);
ev_io_start(stream->loop->ev, &stream->write_watcher);
if (stream->delayed_error) {
ev_feed_event(stream->loop->ev, &stream->write_watcher, EV_WRITE);
}
if (stream->delayed_error)
uv__make_pending(stream);
return 0;
}
@ -961,7 +978,7 @@ int uv__read_start_common(uv_stream_t* stream, uv_alloc_cb alloc_cb,
/* The UV_STREAM_READING flag is irrelevant of the state of the tcp - it just
* expresses the desired state of the user.
*/
((uv_handle_t*)stream)->flags |= UV_STREAM_READING;
stream->flags |= UV_STREAM_READING;
/* TODO: try to do the read inline? */
/* TODO: keep track of tcp state. If we've gotten a EOF then we should
@ -978,6 +995,8 @@ int uv__read_start_common(uv_stream_t* stream, uv_alloc_cb alloc_cb,
assert(stream->read_watcher.cb == uv__stream_io);
ev_io_start(stream->loop->ev, &stream->read_watcher);
uv__handle_start(stream);
return 0;
}
@ -996,6 +1015,7 @@ int uv_read2_start(uv_stream_t* stream, uv_alloc_cb alloc_cb,
int uv_read_stop(uv_stream_t* stream) {
ev_io_stop(stream->loop->ev, &stream->read_watcher);
uv__handle_stop(stream);
stream->flags &= ~UV_STREAM_READING;
stream->read_cb = NULL;
stream->read2_cb = NULL;

View File

@ -189,6 +189,7 @@ int uv_fs_event_init(uv_loop_t* loop,
}
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
uv__handle_start(handle); /* FIXME shouldn't start automatically */
handle->filename = strdup(filename);
handle->fd = PORT_UNUSED;
handle->cb = cb;
@ -200,7 +201,6 @@ int uv_fs_event_init(uv_loop_t* loop,
if (first_run) {
ev_io_init(&loop->fs_event_watcher, uv__fs_event_read, portfd, EV_READ);
ev_io_start(loop->ev, &loop->fs_event_watcher);
ev_unref(loop->ev);
}
return 0;

View File

@ -31,16 +31,14 @@ static int uv__timer_repeating(const uv_timer_t* timer) {
static void uv__timer_cb(EV_P_ ev_timer* w, int revents) {
uv_timer_t* timer = container_of(w, uv_timer_t, timer_watcher);
assert(uv__timer_active(timer));
if (!uv__is_active(timer))
return;
if (!uv__timer_repeating(timer)) {
timer->flags &= ~UV_TIMER_ACTIVE;
ev_ref(EV_A);
}
if (!uv__timer_repeating(timer))
uv__handle_stop(timer);
if (timer->timer_cb) {
if (timer->timer_cb)
timer->timer_cb(timer, 0);
}
}
@ -56,12 +54,11 @@ int uv_timer_init(uv_loop_t* loop, uv_timer_t* timer) {
int uv_timer_start(uv_timer_t* timer, uv_timer_cb cb, int64_t timeout,
int64_t repeat) {
if (uv__timer_active(timer)) {
if (uv__is_active(timer)) {
return -1;
}
timer->timer_cb = cb;
timer->flags |= UV_TIMER_ACTIVE;
if (repeat)
timer->flags |= UV_TIMER_REPEAT;
@ -70,26 +67,22 @@ int uv_timer_start(uv_timer_t* timer, uv_timer_cb cb, int64_t timeout,
ev_timer_set(&timer->timer_watcher, timeout / 1000.0, repeat / 1000.0);
ev_timer_start(timer->loop->ev, &timer->timer_watcher);
ev_unref(timer->loop->ev);
uv__handle_start(timer);
return 0;
}
int uv_timer_stop(uv_timer_t* timer) {
if (uv__timer_active(timer)) {
ev_ref(timer->loop->ev);
}
timer->flags &= ~(UV_TIMER_ACTIVE | UV_TIMER_REPEAT);
timer->flags &= ~UV_TIMER_REPEAT;
ev_timer_stop(timer->loop->ev, &timer->timer_watcher);
uv__handle_stop(timer);
return 0;
}
int uv_timer_again(uv_timer_t* timer) {
if (!uv__timer_active(timer)) {
if (!uv__is_active(timer)) {
uv__set_artificial_error(timer->loop, UV_EINVAL);
return -1;
}
@ -117,11 +110,6 @@ int64_t uv_timer_get_repeat(uv_timer_t* timer) {
}
int uv__timer_active(const uv_timer_t* timer) {
return timer->flags & UV_TIMER_ACTIVE;
}
void uv__timer_close(uv_timer_t* handle) {
uv_timer_stop(handle);
}

View File

@ -46,16 +46,20 @@ static void uv__udp_start_watcher(uv_udp_t* handle,
ev_set_cb(w, cb);
ev_io_set(w, handle->fd, flags);
ev_io_start(handle->loop->ev, w);
ev_unref(handle->loop->ev);
uv__handle_start(handle);
}
static void uv__udp_stop_watcher(uv_udp_t* handle, ev_io* w) {
if (!ev_is_active(w)) return;
ev_ref(handle->loop->ev);
ev_io_stop(handle->loop->ev, w);
ev_io_set(w, -1, 0);
ev_set_cb(w, NULL);
if (!ev_is_active(&handle->read_watcher) &&
!ev_is_active(&handle->write_watcher)) {
uv__handle_stop(handle);
}
}
@ -108,6 +112,8 @@ void uv__udp_finish_close(uv_udp_t* handle) {
ngx_queue_remove(q);
req = ngx_queue_data(q, uv_udp_send_t, queue);
uv__req_unregister(handle->loop, req);
if (req->send_cb) {
/* FIXME proper error code like UV_EABORTED */
uv__set_artificial_error(handle->loop, UV_EINTR);
@ -185,12 +191,10 @@ static void uv__udp_run_completed(uv_udp_t* handle) {
while (!ngx_queue_empty(&handle->write_completed_queue)) {
q = ngx_queue_head(&handle->write_completed_queue);
assert(q != NULL);
ngx_queue_remove(q);
req = ngx_queue_data(q, uv_udp_send_t, queue);
assert(req != NULL);
uv__req_unregister(handle->loop, req);
if (req->bufs != req->bufsml)
free(req->bufs);

View File

@ -27,47 +27,31 @@
#include <stdio.h>
static uv_once_t uv__eio_init_once_guard = UV_ONCE_INIT;
static void uv_eio_do_poll(uv_idle_t* watcher, int status) {
assert(watcher == &(watcher->loop->uv_eio_poller));
/* printf("uv_eio_poller\n"); */
if (eio_poll(&watcher->loop->uv_eio_channel) != -1 && uv_is_active((uv_handle_t*) watcher)) {
/* printf("uv_eio_poller stop\n"); */
uv_loop_t* loop = watcher->loop;
assert(watcher == &loop->uv_eio_poller);
if (eio_poll(&loop->uv_eio_channel) != -1)
uv_idle_stop(watcher);
uv_unref(watcher->loop);
}
}
/* Called from the main thread. */
static void uv_eio_want_poll_notifier_cb(uv_async_t* watcher, int status) {
uv_loop_t* loop = watcher->loop;
assert(watcher == &loop->uv_eio_want_poll_notifier);
/* printf("want poll notifier\n"); */
if (eio_poll(&watcher->loop->uv_eio_channel) == -1 && !uv_is_active((uv_handle_t*) &loop->uv_eio_poller)) {
/* printf("uv_eio_poller start\n"); */
if (eio_poll(&loop->uv_eio_channel) == -1)
uv_idle_start(&loop->uv_eio_poller, uv_eio_do_poll);
uv_ref(loop);
}
}
static void uv_eio_done_poll_notifier_cb(uv_async_t* watcher, int revents) {
uv_loop_t* loop = watcher->loop;
assert(watcher == &loop->uv_eio_done_poll_notifier);
/* printf("done poll notifier\n"); */
if (eio_poll(&watcher->loop->uv_eio_channel) != -1 && uv_is_active((uv_handle_t*) &loop->uv_eio_poller)) {
/* printf("uv_eio_poller stop\n"); */
if (eio_poll(&loop->uv_eio_channel) != -1)
uv_idle_stop(&loop->uv_eio_poller);
uv_unref(loop);
}
}
@ -100,12 +84,10 @@ static void uv__eio_init(void) {
eio_init(uv_eio_want_poll, uv_eio_done_poll);
}
static uv_once_t uv__eio_init_once_guard = UV_ONCE_INIT;
void uv_eio_init(uv_loop_t* loop) {
if (loop->counters.eio_init == 0) {
loop->counters.eio_init++;
if (loop->counters.eio_init) return;
loop->counters.eio_init = 1;
uv_idle_init(loop, &loop->uv_eio_poller);
uv_idle_start(&loop->uv_eio_poller, uv_eio_do_poll);
@ -113,12 +95,9 @@ void uv_eio_init(uv_loop_t* loop) {
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_unref(loop);
uv_async_init(loop, &loop->uv_eio_done_poll_notifier,
uv_eio_done_poll_notifier_cb);
uv_unref(loop);
uv_once(&uv__eio_init_once_guard, uv__eio_init);
}
}

View File

@ -352,3 +352,13 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
return 0;
}
void uv_ref(uv_handle_t* handle) {
uv__handle_ref(handle);
}
void uv_unref(uv_handle_t* handle) {
uv__handle_unref(handle);
}

View File

@ -27,11 +27,30 @@
#ifndef UV_COMMON_H_
#define UV_COMMON_H_
#include <assert.h>
#include "uv.h"
#include "tree.h"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#ifdef _MSC_VER
# define UNUSED /* empty */
#else
# define UNUSED __attribute__((unused))
#endif
#ifndef _WIN32
enum {
UV__ACTIVE = 0x4000,
UV__REF = 0x8000
};
#else
# define UV__REF 0x00000020
# define UV__ACTIVE 0x00000040
#endif
struct uv_ares_task_s {
UV_HANDLE_FIELDS
@ -83,5 +102,105 @@ int uv__tcp_connect6(uv_connect_t* req,
struct sockaddr_in6 address,
uv_connect_cb cb);
#ifndef UV_LEAN_AND_MEAN
UNUSED static int uv__has_active_handles(const uv_loop_t* loop) {
return !ngx_queue_empty(&loop->active_handles);
}
UNUSED static int uv__has_active_reqs(const uv_loop_t* loop) {
return !ngx_queue_empty(&loop->active_reqs);
}
UNUSED static void uv__active_handle_add(uv_handle_t* h) {
ngx_queue_insert_tail(&h->loop->active_handles, &h->active_queue);
}
UNUSED static void uv__active_handle_rm(uv_handle_t* h) {
assert(uv__has_active_handles(h->loop));
ngx_queue_remove(&h->active_queue);
}
UNUSED static void uv__req_register(uv_loop_t* loop, uv_req_t* req) {
ngx_queue_insert_tail(&loop->active_reqs, &req->active_queue);
}
UNUSED static void uv__req_unregister(uv_loop_t* loop, uv_req_t* req) {
assert(uv__has_active_reqs(loop));
ngx_queue_remove(&req->active_queue);
}
#else /* UV_LEAN_AND_MEAN */
UNUSED static int uv__has_active_handles(const uv_loop_t* loop) {
return loop->active_handles > 0;
}
UNUSED static int uv__has_active_reqs(const uv_loop_t* loop) {
return loop->active_reqs > 0;
}
UNUSED static void uv__active_handle_add(uv_handle_t* h) {
h->loop->active_handles++;
}
UNUSED static void uv__active_handle_rm(uv_handle_t* h) {
assert(h->loop->active_handles > 0);
h->loop->active_handles--;
}
UNUSED static void uv__req_register(uv_loop_t* loop, uv_req_t* req) {
loop->active_reqs++;
(void) req;
}
UNUSED static void uv__req_unregister(uv_loop_t* loop, uv_req_t* req) {
assert(loop->active_reqs > 0);
loop->active_reqs--;
(void) req;
}
#endif /* UV_LEAN_AND_MEAN */
#define uv__active_handle_add(h) uv__active_handle_add((uv_handle_t*)(h))
#define uv__active_handle_rm(h) uv__active_handle_rm((uv_handle_t*)(h))
#define uv__req_register(loop, req) uv__req_register((loop), (uv_req_t*)(req))
#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);
}
#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)) return;
h->flags |= UV__ACTIVE;
uv__active_handle_add(h);
}
#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)) return;
uv__active_handle_rm(h);
h->flags &= ~UV__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;
}
#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;
}
#define uv__handle_unref(h) uv__handle_unref((uv_handle_t*)(h))
#endif /* UV_COMMON_H_ */

View File

@ -59,12 +59,11 @@ void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle) {
!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_unref(loop);
}
}
@ -72,12 +71,8 @@ void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle) {
int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
uv_req_t* req;
loop->counters.handle_init++;
loop->counters.async_init++;
uv_handle_init(loop, (uv_handle_t*) handle);
handle->type = UV_ASYNC;
handle->loop = loop;
handle->flags = 0;
handle->async_sent = 0;
handle->async_cb = async_cb;
@ -86,12 +81,23 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
req->type = UV_WAKEUP;
req->data = handle;
uv_ref(loop);
loop->counters.async_init++;
uv__handle_start(handle);
return 0;
}
void uv_async_close(uv_loop_t* loop, uv_async_t* handle) {
if (!((uv_async_t*)handle)->async_sent) {
uv_want_endgame(loop, (uv_handle_t*) handle);
}
uv__handle_start(handle);
}
int uv_async_send(uv_async_t* handle) {
uv_loop_t* loop = handle->loop;

View File

@ -22,7 +22,6 @@
#include <assert.h>
#include "uv.h"
#include "../uv-common.h"
#include "internal.h"
@ -132,6 +131,7 @@ static void uv_ares_sockstate_cb(void *data, ares_socket_t sock, int read,
}
/* remove handle from list */
uv_remove_ares_handle(uv_handle_ares);
uv__handle_stop(uv_handle_ares);
/* Post request to cleanup the Task */
uv_ares_req = &uv_handle_ares->ares_req;
@ -178,7 +178,7 @@ static void uv_ares_sockstate_cb(void *data, ares_socket_t sock, int read,
/* add handle to list */
uv_add_ares_handle(loop, uv_handle_ares);
uv_ref(loop);
uv__handle_start(uv_handle_ares);
/*
* we have a single polling timer for all ares sockets.
@ -229,7 +229,7 @@ void uv_process_ares_cleanup_req(uv_loop_t* loop, uv_ares_task_t* handle,
unsigned int signaled = WaitForSingleObject(handle->h_close_event, 0);
if (signaled != WAIT_TIMEOUT) {
uv_unref(loop);
uv__handle_stop(loop);
/* close event handle and free uv handle memory */
CloseHandle(handle->h_close_event);

View File

@ -27,7 +27,6 @@
#include <string.h>
#include "uv.h"
#include "../uv-common.h"
#include "internal.h"
@ -65,10 +64,16 @@ static void uv_loop_init(uv_loop_t* loop) {
uv_fatal_error(GetLastError(), "CreateIoCompletionPort");
}
loop->refs = 0;
uv_update_time(loop);
#ifndef UV_LEAN_AND_MEAN
ngx_queue_init(&loop->active_handles);
ngx_queue_init(&loop->active_reqs);
#else
loop->active_handles = 0;
loop->active_reqs = 0;
#endif
loop->pending_reqs_tail = NULL;
loop->endgame_handles = NULL;
@ -145,21 +150,6 @@ void uv_loop_delete(uv_loop_t* loop) {
}
int uv_loop_refcount(const uv_loop_t* loop) {
return loop->refs;
}
void uv_ref(uv_loop_t* loop) {
loop->refs++;
}
void uv_unref(uv_loop_t* loop) {
loop->refs--;
}
static void uv_poll(uv_loop_t* loop, int block) {
BOOL success;
DWORD bytes, timeout;
@ -226,6 +216,19 @@ static void uv_poll_ex(uv_loop_t* loop, int block) {
}
}
#ifndef UV_LEAN_AND_MEAN
# define UV_LOOP_ALIVE(loop) \
(!ngx_queue_empty(&(loop)->active_handles) || \
!ngx_queue_empty(&(loop)->active_reqs) || \
(loop)->endgame_handles != NULL)
#else
# define UV_LOOP_ALIVE(loop) \
((loop)->active_handles > 0 && \
(loop)->active_reqs > 0 && \
(loop)->endgame_handles != NULL)
#endif
#define UV_LOOP_ONCE(loop, poll) \
do { \
uv_update_time((loop)); \
@ -240,7 +243,7 @@ static void uv_poll_ex(uv_loop_t* loop, int block) {
uv_process_reqs((loop)); \
uv_process_endgames((loop)); \
\
if ((loop)->refs <= 0) { \
if (!UV_LOOP_ALIVE((loop))) { \
break; \
} \
\
@ -249,13 +252,13 @@ static void uv_poll_ex(uv_loop_t* loop, int block) {
poll((loop), (loop)->idle_handles == NULL && \
(loop)->pending_reqs_tail == NULL && \
(loop)->endgame_handles == NULL && \
(loop)->refs > 0); \
UV_LOOP_ALIVE((loop))); \
\
uv_check_invoke((loop)); \
} while (0);
#define UV_LOOP(loop, poll) \
while ((loop)->refs > 0) { \
while (UV_LOOP_ALIVE((loop))) { \
UV_LOOP_ONCE(loop, poll) \
}
@ -277,6 +280,6 @@ int uv_run(uv_loop_t* loop) {
UV_LOOP(loop, uv_poll);
}
assert(loop->refs == 0);
assert(!UV_LOOP_ALIVE((loop)));
return 0;
}

View File

@ -26,7 +26,6 @@
#include <string.h>
#include "uv.h"
#include "../uv-common.h"
#include "internal.h"

View File

@ -19,13 +19,14 @@
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "internal.h"
#include <assert.h>
#include <malloc.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "uv.h"
#include "internal.h"
const unsigned int uv_directory_watcher_buffer_size = 4096;
@ -33,9 +34,8 @@ const unsigned int uv_directory_watcher_buffer_size = 4096;
static void uv_fs_event_init_handle(uv_loop_t* loop, uv_fs_event_t* handle,
const char* filename, uv_fs_event_cb cb) {
uv_handle_init(loop, (uv_handle_t*) handle);
handle->type = UV_FS_EVENT;
handle->loop = loop;
handle->flags = 0;
handle->cb = cb;
handle->dir_handle = INVALID_HANDLE_VALUE;
handle->buffer = NULL;
@ -53,10 +53,9 @@ static void uv_fs_event_init_handle(uv_loop_t* loop, uv_fs_event_t* handle,
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}
loop->counters.handle_init++;
loop->counters.fs_event_init++;
uv__handle_start(handle);
uv_ref(loop);
loop->counters.fs_event_init++;
}
@ -471,6 +470,8 @@ void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) {
if (!handle->req_pending) {
uv_want_endgame(loop, (uv_handle_t*)handle);
}
uv__handle_start(handle);
}
@ -479,6 +480,7 @@ void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
!handle->req_pending) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
handle->flags |= UV_HANDLE_CLOSED;
uv__handle_stop(handle);
if (handle->buffer) {
_aligned_free(handle->buffer);
@ -508,7 +510,5 @@ void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
if (handle->close_cb) {
handle->close_cb((uv_handle_t*)handle);
}
uv_unref(loop);
}
}

View File

@ -59,7 +59,7 @@
return -1; \
} \
req->flags |= UV_FS_ASYNC_QUEUED; \
uv_ref((loop));
uv__req_register(loop, req);
#define SET_UV_LAST_ERROR_FROM_REQ(req) \
uv__set_error(req->loop, req->errorno, req->sys_errno_);
@ -1519,6 +1519,7 @@ int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime,
void uv_process_fs_req(uv_loop_t* loop, uv_fs_t* req) {
assert(req->cb);
uv__req_unregister(loop, req);
SET_UV_LAST_ERROR_FROM_REQ(req);
req->cb(req);
}
@ -1552,10 +1553,6 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
req->path = NULL;
}
if (req->flags & UV_FS_ASYNC_QUEUED) {
uv_unref(loop);
}
req->flags |= UV_FS_CLEANEDUP;
}

View File

@ -77,23 +77,21 @@ static uv_err_code uv_translate_eai_error(int eai_errno) {
/* getaddrinfo worker thread implementation */
static DWORD WINAPI getaddrinfo_thread_proc(void* parameter) {
uv_getaddrinfo_t* handle = (uv_getaddrinfo_t*) parameter;
uv_loop_t* loop = handle->loop;
uv_getaddrinfo_t* req = (uv_getaddrinfo_t*) parameter;
uv_loop_t* loop = req->loop;
int ret;
assert(handle != NULL);
assert(req != NULL);
if (handle != NULL) {
/* call OS function on this thread */
ret = GetAddrInfoW(handle->node,
handle->service,
handle->hints,
&handle->res);
handle->retcode = ret;
ret = GetAddrInfoW(req->node,
req->service,
req->hints,
&req->res);
req->retcode = ret;
/* post getaddrinfo completed */
POST_COMPLETION_FOR_REQ(loop, &handle->getadddrinfo_req);
}
POST_COMPLETION_FOR_REQ(loop, req);
return 0;
}
@ -108,8 +106,7 @@ static DWORD WINAPI getaddrinfo_thread_proc(void* parameter) {
* and copy all structs and referenced strings into the one block.
* Each size calculation is adjusted to avoid unaligned pointers.
*/
void uv_process_getaddrinfo_req(uv_loop_t* loop, uv_getaddrinfo_t* handle,
uv_req_t* req) {
void uv_process_getaddrinfo_req(uv_loop_t* loop, uv_getaddrinfo_t* req) {
int addrinfo_len = 0;
int name_len = 0;
size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo));
@ -120,15 +117,15 @@ void uv_process_getaddrinfo_req(uv_loop_t* loop, uv_getaddrinfo_t* handle,
int status = 0;
/* release input parameter memory */
if (handle->alloc != NULL) {
free(handle->alloc);
handle->alloc = NULL;
if (req->alloc != NULL) {
free(req->alloc);
req->alloc = NULL;
}
if (handle->retcode == 0) {
if (req->retcode == 0) {
/* convert addrinfoW to addrinfo */
/* first calculate required length */
addrinfow_ptr = handle->res;
addrinfow_ptr = req->res;
while (addrinfow_ptr != NULL) {
addrinfo_len += addrinfo_struct_len +
ALIGNED_SIZE(addrinfow_ptr->ai_addrlen);
@ -150,7 +147,7 @@ void uv_process_getaddrinfo_req(uv_loop_t* loop, uv_getaddrinfo_t* handle,
/* do conversions */
if (alloc_ptr != NULL) {
cur_ptr = alloc_ptr;
addrinfow_ptr = handle->res;
addrinfow_ptr = req->res;
while (addrinfow_ptr != NULL) {
/* copy addrinfo struct data */
@ -206,21 +203,21 @@ void uv_process_getaddrinfo_req(uv_loop_t* loop, uv_getaddrinfo_t* handle,
}
} else {
/* GetAddrInfo failed */
uv__set_artificial_error(loop, uv_translate_eai_error(handle->retcode));
uv__set_artificial_error(loop, uv_translate_eai_error(req->retcode));
status = -1;
}
/* return memory to system */
if (handle->res != NULL) {
FreeAddrInfoW(handle->res);
handle->res = NULL;
if (req->res != NULL) {
FreeAddrInfoW(req->res);
req->res = NULL;
}
complete:
/* finally do callback with converted result */
handle->getaddrinfo_cb(handle, status, (struct addrinfo*)alloc_ptr);
uv__req_unregister(loop, req);
uv_unref(loop);
/* finally do callback with converted result */
req->getaddrinfo_cb(req, status, (struct addrinfo*)alloc_ptr);
}
@ -237,7 +234,7 @@ void uv_freeaddrinfo(struct addrinfo* ai) {
/*
* Entry point for getaddrinfo
* we convert the UTF-8 strings to UNICODE
* and save the UNICODE string pointers in the handle
* and save the UNICODE string pointers in the req
* We also copy hints so that caller does not need to keep memory until the
* callback.
* return UV_OK if a callback will be made
@ -248,7 +245,7 @@ void uv_freeaddrinfo(struct addrinfo* ai) {
* Each size calculation is adjusted to avoid unaligned pointers.
*/
int uv_getaddrinfo(uv_loop_t* loop,
uv_getaddrinfo_t* handle,
uv_getaddrinfo_t* req,
uv_getaddrinfo_cb getaddrinfo_cb,
const char* node,
const char* service,
@ -258,18 +255,18 @@ int uv_getaddrinfo(uv_loop_t* loop,
int hintssize = 0;
char* alloc_ptr = NULL;
if (handle == NULL || getaddrinfo_cb == NULL ||
if (req == NULL || getaddrinfo_cb == NULL ||
(node == NULL && service == NULL)) {
uv__set_sys_error(loop, WSAEINVAL);
goto error;
}
uv_req_init(loop, (uv_req_t*)handle);
uv_req_init(loop, (uv_req_t*)req);
handle->getaddrinfo_cb = getaddrinfo_cb;
handle->res = NULL;
handle->type = UV_GETADDRINFO;
handle->loop = loop;
req->getaddrinfo_cb = getaddrinfo_cb;
req->res = NULL;
req->type = UV_GETADDRINFO;
req->loop = loop;
/* calculate required memory size for all input values */
if (node != NULL) {
@ -300,12 +297,12 @@ int uv_getaddrinfo(uv_loop_t* loop,
}
/* save alloc_ptr now so we can free if error */
handle->alloc = (void*)alloc_ptr;
req->alloc = (void*)alloc_ptr;
/* convert node string to UTF16 into allocated memory and save pointer in */
/* handle */
/* the reques. */
if (node != NULL) {
handle->node = (wchar_t*)alloc_ptr;
req->node = (wchar_t*)alloc_ptr;
if (uv_utf8_to_utf16(node,
(wchar_t*) alloc_ptr,
nodesize / sizeof(wchar_t)) == 0) {
@ -314,13 +311,13 @@ int uv_getaddrinfo(uv_loop_t* loop,
}
alloc_ptr += nodesize;
} else {
handle->node = NULL;
req->node = NULL;
}
/* convert service string to UTF16 into allocated memory and save pointer */
/* in handle */
/* in the req. */
if (service != NULL) {
handle->service = (wchar_t*)alloc_ptr;
req->service = (wchar_t*)alloc_ptr;
if (uv_utf8_to_utf16(service,
(wchar_t*) alloc_ptr,
servicesize / sizeof(wchar_t)) == 0) {
@ -329,44 +326,39 @@ int uv_getaddrinfo(uv_loop_t* loop,
}
alloc_ptr += servicesize;
} else {
handle->service = NULL;
req->service = NULL;
}
/* copy hints to allocated memory and save pointer in handle */
/* copy hints to allocated memory and save pointer in req */
if (hints != NULL) {
handle->hints = (struct addrinfoW*)alloc_ptr;
handle->hints->ai_family = hints->ai_family;
handle->hints->ai_socktype = hints->ai_socktype;
handle->hints->ai_protocol = hints->ai_protocol;
handle->hints->ai_flags = hints->ai_flags;
handle->hints->ai_addrlen = 0;
handle->hints->ai_canonname = NULL;
handle->hints->ai_addr = NULL;
handle->hints->ai_next = NULL;
req->hints = (struct addrinfoW*)alloc_ptr;
req->hints->ai_family = hints->ai_family;
req->hints->ai_socktype = hints->ai_socktype;
req->hints->ai_protocol = hints->ai_protocol;
req->hints->ai_flags = hints->ai_flags;
req->hints->ai_addrlen = 0;
req->hints->ai_canonname = NULL;
req->hints->ai_addr = NULL;
req->hints->ai_next = NULL;
} else {
handle->hints = NULL;
req->hints = NULL;
}
/* init request for Post handling */
uv_req_init(loop, &handle->getadddrinfo_req);
handle->getadddrinfo_req.data = handle;
handle->getadddrinfo_req.type = UV_GETADDRINFO_REQ;
/* Ask thread to run. Treat this as a long operation */
if (QueueUserWorkItem(&getaddrinfo_thread_proc,
handle,
req,
WT_EXECUTELONGFUNCTION) == 0) {
uv__set_sys_error(loop, GetLastError());
goto error;
}
uv_ref(loop);
uv__req_register(loop, req);
return 0;
error:
if (handle != NULL && handle->alloc != NULL) {
free(handle->alloc);
if (req != NULL && req->alloc != NULL) {
free(req->alloc);
}
return -1;
}

View File

@ -57,30 +57,23 @@ uv_handle_type uv_guess_handle(uv_file file) {
int uv_is_active(const uv_handle_t* handle) {
switch (handle->type) {
case UV_TIMER:
case UV_IDLE:
case UV_PREPARE:
case UV_CHECK:
return (handle->flags & UV_HANDLE_ACTIVE) ? 1 : 0;
return (handle->flags & UV__ACTIVE) && !(handle->flags & UV_HANDLE_CLOSING);
}
case UV_POLL:
return ((uv_poll_t*) handle)->events != 0;
default:
return 1;
}
void uv_handle_init(uv_loop_t* loop, uv_handle_t* handle) {
handle->loop = loop;
handle->flags = UV__REF;
loop->counters.handle_init++;
}
void uv_close(uv_handle_t* handle, uv_close_cb cb) {
uv_pipe_t* pipe;
uv_udp_t* udp;
uv_process_t* process;
uv_loop_t* loop = handle->loop;
if (handle->flags & UV_HANDLE_CLOSING) {
assert(0);
return;
}
@ -90,16 +83,11 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
/* Handle-specific close actions */
switch (handle->type) {
case UV_TCP:
uv_tcp_close((uv_tcp_t*)handle);
uv_tcp_close(loop, (uv_tcp_t*)handle);
return;
case UV_NAMED_PIPE:
pipe = (uv_pipe_t*)handle;
pipe->flags &= ~(UV_HANDLE_READING | UV_HANDLE_LISTENING);
close_pipe(pipe, NULL, NULL);
if (pipe->reqs_pending == 0) {
uv_want_endgame(loop, handle);
}
uv_pipe_close(loop, (uv_pipe_t*) handle);
return;
case UV_TTY:
@ -107,51 +95,47 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
return;
case UV_UDP:
udp = (uv_udp_t*) handle;
uv_udp_recv_stop(udp);
closesocket(udp->socket);
if (udp->reqs_pending == 0) {
uv_want_endgame(loop, handle);
}
uv_udp_close(loop, (uv_udp_t*) handle);
return;
case UV_POLL:
uv_poll_close(handle->loop, (uv_poll_t*) handle);
uv_poll_close(loop, (uv_poll_t*) handle);
return;
case UV_TIMER:
uv_timer_stop((uv_timer_t*)handle);
uv__handle_start(handle);
uv_want_endgame(loop, handle);
return;
case UV_PREPARE:
uv_prepare_stop((uv_prepare_t*)handle);
uv__handle_start(handle);
uv_want_endgame(loop, handle);
return;
case UV_CHECK:
uv_check_stop((uv_check_t*)handle);
uv__handle_start(handle);
uv_want_endgame(loop, handle);
return;
case UV_IDLE:
uv_idle_stop((uv_idle_t*)handle);
uv__handle_start(handle);
uv_want_endgame(loop, handle);
return;
case UV_ASYNC:
if (!((uv_async_t*)handle)->async_sent) {
uv_want_endgame(loop, handle);
}
uv_async_close(loop, (uv_async_t*) handle);
return;
case UV_PROCESS:
process = (uv_process_t*)handle;
uv_process_close(loop, process);
uv_process_close(loop, (uv_process_t*) handle);
return;
case UV_FS_EVENT:
uv_fs_event_close(loop, (uv_fs_event_t*)handle);
uv_fs_event_close(loop, (uv_fs_event_t*) handle);
return;
default:
@ -179,7 +163,7 @@ void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle) {
void uv_process_endgames(uv_loop_t* loop) {
uv_handle_t* handle;
while (loop->endgame_handles && loop->refs > 0) {
while (loop->endgame_handles) {
handle = loop->endgame_handles;
loop->endgame_handles = handle->endgame_next;

View File

@ -30,15 +30,6 @@
#include "winsock.h"
/*
* Timers
*/
void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle);
DWORD uv_get_poll_timeout(uv_loop_t* loop);
void uv_process_timers(uv_loop_t* loop);
/*
* Handles
*/
@ -47,10 +38,14 @@ void uv_process_timers(uv_loop_t* loop);
#define UV_HANDLE_CLOSING 0x00000001
#define UV_HANDLE_CLOSED 0x00000002
#define UV_HANDLE_ENDGAME_QUEUED 0x00000004
#define UV_HANDLE_UV_ALLOCED 0x00000008
#define UV_HANDLE_ACTIVE 0x00000010
/* Used by streams. */
/* Keep in sync with uv-common.h: */
#define UV__REF 0x00000020
#define UV__ACTIVE 0x00000040
/* reserved: #define UV_HANDLE_INTERNAL 0x00000080 */
/* Used by streams and UDP handles. */
#define UV_HANDLE_READING 0x00000100
#define UV_HANDLE_BOUND 0x00000200
#define UV_HANDLE_BIND_ERROR 0x00000400
@ -72,8 +67,7 @@ void uv_process_timers(uv_loop_t* loop);
#define UV_HANDLE_TCP_SINGLE_ACCEPT 0x08000000
#define UV_HANDLE_TCP_ACCEPT_STATE_CHANGING 0x10000000
#define UV_HANDLE_TCP_SOCKET_CLOSED 0x20000000
#define UV_HANDLE_SHARED_TCP_SERVER 0x40000000
#define UV_HANDLE_SHARED_TCP_SOCKET 0x80000000
#define UV_HANDLE_SHARED_TCP_SOCKET 0x40000000
/* Only used by uv_pipe_t handles. */
#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x01000000
@ -108,6 +102,41 @@ void uv_process_endgames(uv_loop_t* loop);
#define UV_SUCCEEDED_WITH_IOCP(result) \
((result) || (GetLastError() == ERROR_IO_PENDING))
#define DECREASE_ACTIVE_COUNT(loop, handle) \
do { \
if (--(handle)->activecnt == 0 && \
!((handle)->flags & UV_HANDLE_CLOSING)) { \
uv__handle_stop((handle)); \
} \
assert((handle)->activecnt >= 0); \
} while (0)
#define INCREASE_ACTIVE_COUNT(loop, handle) \
do { \
if ((handle)->activecnt++ == 0) { \
uv__handle_start((handle)); \
} \
assert((handle)->activecnt > 0); \
} while (0)
#define REGISTER_HANDLE_REQ(loop, handle, req) \
do { \
INCREASE_ACTIVE_COUNT((loop), (handle)); \
uv__req_register((loop), (req)); \
} while (0)
#define UNREGISTER_HANDLE_REQ(loop, handle, req) \
do { \
DECREASE_ACTIVE_COUNT((loop), (handle)); \
uv__req_unregister((loop), (req)); \
} while (0)
/*
* Handles
*/
void uv_handle_init(uv_loop_t* loop, uv_handle_t* handle);
/*
* Requests
@ -155,6 +184,7 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
uv_connect_t* req);
void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp);
void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle);
int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info,
@ -163,8 +193,6 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info,
int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid,
LPWSAPROTOCOL_INFOW protocol_info);
void uv_tcp_close(uv_tcp_t* tcp);
/*
* UDP
@ -173,6 +201,7 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, uv_req_t* req);
void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
uv_udp_send_t* req);
void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle);
void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle);
@ -181,8 +210,6 @@ void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle);
*/
int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
char* name, size_t nameSize);
void close_pipe(uv_pipe_t* handle, int* status, uv_err_t* err);
void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle);
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client);
@ -206,6 +233,10 @@ void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle,
void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
uv_shutdown_t* req);
void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle);
void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle);
void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle);
/*
* TTY
@ -243,6 +274,15 @@ void uv_poll_close(uv_loop_t* loop, uv_poll_t* handle);
void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle);
/*
* Timers
*/
void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle);
DWORD uv_get_poll_timeout(uv_loop_t* loop);
void uv_process_timers(uv_loop_t* loop);
/*
* Loop watchers
*/
@ -256,6 +296,7 @@ void uv_idle_invoke(uv_loop_t* loop);
/*
* Async watcher
*/
void uv_async_close(uv_loop_t* loop, uv_async_t* handle);
void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle);
void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
@ -284,8 +325,7 @@ void uv_process_ares_cleanup_req(uv_loop_t* loop, uv_ares_task_t* handle,
/*
* Getaddrinfo
*/
void uv_process_getaddrinfo_req(uv_loop_t* loop, uv_getaddrinfo_t* handle,
uv_req_t* req);
void uv_process_getaddrinfo_req(uv_loop_t* loop, uv_getaddrinfo_t* req);
/*

View File

@ -22,7 +22,6 @@
#include <assert.h>
#include "uv.h"
#include "../uv-common.h"
#include "internal.h"
@ -30,25 +29,19 @@ void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_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(handle);
}
uv_unref(loop);
}
}
#define UV_LOOP_WATCHER_DEFINE(name, NAME) \
int uv_##name##_init(uv_loop_t* loop, uv_##name##_t* handle) { \
uv_handle_init(loop, (uv_handle_t*) handle); \
handle->type = UV_##NAME; \
handle->loop = loop; \
handle->flags = 0; \
\
uv_ref(loop); \
\
loop->counters.handle_init++; \
loop->counters.name##_init++; \
\
return 0; \
@ -77,6 +70,7 @@ void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) {
\
handle->name##_cb = cb; \
handle->flags |= UV_HANDLE_ACTIVE; \
uv__handle_start(handle); \
\
return 0; \
} \
@ -108,6 +102,7 @@ void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) {
} \
\
handle->flags &= ~UV_HANDLE_ACTIVE; \
uv__handle_stop(handle); \
\
return 0; \
} \

View File

@ -25,7 +25,6 @@
#include <stdio.h>
#include "uv.h"
#include "../uv-common.h"
#include "internal.h"
@ -280,7 +279,6 @@ static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) {
void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
unsigned int uv_alloced;
DWORD result;
uv_shutdown_t* req;
NTSTATUS nt_status;
@ -296,12 +294,14 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
handle->shutdown_req = NULL;
if (handle->flags & UV_HANDLE_CLOSING) {
UNREGISTER_HANDLE_REQ(loop, handle, req);
/* Already closing. Cancel the shutdown. */
if (req->cb) {
uv__set_sys_error(loop, WSAEINTR);
req->cb(req, -1);
}
uv_unref(loop);
DECREASE_PENDING_REQ_COUNT(handle);
return;
}
@ -315,12 +315,14 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
if (nt_status != STATUS_SUCCESS) {
/* Failure */
UNREGISTER_HANDLE_REQ(loop, handle, req);
handle->flags &= ~UV_HANDLE_SHUTTING;
if (req->cb) {
uv__set_sys_error(loop, pRtlNtStatusToDosError(nt_status));
req->cb(req, -1);
}
uv_unref(loop);
DECREASE_PENDING_REQ_COUNT(handle);
return;
}
@ -340,12 +342,14 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
} else {
/* Failure. */
UNREGISTER_HANDLE_REQ(loop, handle, req);
handle->flags &= ~UV_HANDLE_SHUTTING;
if (req->cb) {
uv__set_sys_error(loop, GetLastError());
req->cb(req, -1);
}
uv_unref(loop);
DECREASE_PENDING_REQ_COUNT(handle);
return;
}
@ -355,6 +359,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
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) {
if (handle->pending_ipc_info.socket_info) {
@ -380,19 +385,9 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
handle->accept_reqs = NULL;
}
/* Remember the state of this flag because the close callback is */
/* allowed to clobber or free the handle's memory */
uv_alloced = handle->flags & UV_HANDLE_UV_ALLOCED;
if (handle->close_cb) {
handle->close_cb((uv_handle_t*)handle);
}
if (uv_alloced) {
free(handle);
}
uv_unref(loop);
}
}
@ -573,7 +568,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
goto error;
}
uv_ref(loop);
REGISTER_HANDLE_REQ(loop, handle, req);
handle->reqs_pending++;
return;
@ -596,7 +591,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
SET_REQ_SUCCESS(req);
uv_insert_pending_req(loop, (uv_req_t*) req);
handle->reqs_pending++;
uv_ref(loop);
REGISTER_HANDLE_REQ(loop, handle, req);
return;
error:
@ -613,14 +608,14 @@ error:
SET_REQ_ERROR(req, errorno);
uv_insert_pending_req(loop, (uv_req_t*) req);
handle->reqs_pending++;
uv_ref(loop);
REGISTER_HANDLE_REQ(loop, handle, req);
return;
}
/* Cleans up uv_pipe_t (server or connection) and all resources associated */
/* with it. */
void close_pipe(uv_pipe_t* handle, int* status, uv_err_t* err) {
void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) {
int i;
HANDLE pipeHandle;
@ -652,6 +647,27 @@ void close_pipe(uv_pipe_t* handle, int* status, uv_err_t* err) {
}
void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle) {
if (handle->flags & UV_HANDLE_READING) {
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, handle);
}
if (handle->flags & UV_HANDLE_LISTENING) {
handle->flags &= ~UV_HANDLE_LISTENING;
DECREASE_ACTIVE_COUNT(loop, handle);
}
uv_pipe_cleanup(loop, handle);
if (handle->reqs_pending == 0) {
uv_want_endgame(loop, (uv_handle_t*) handle);
}
uv__handle_start(handle);
}
static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle,
uv_pipe_accept_t* req, BOOL firstInstance) {
assert(handle->flags & UV_HANDLE_LISTENING);
@ -753,17 +769,19 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
/* Starts listening for connections for the given pipe. */
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
uv_loop_t* loop = handle->loop;
int i;
if (handle->flags & UV_HANDLE_LISTENING) {
handle->connection_cb = cb;
}
if (!(handle->flags & UV_HANDLE_BOUND)) {
uv__set_artificial_error(loop, UV_EINVAL);
return -1;
}
if (handle->flags & UV_HANDLE_LISTENING ||
handle->flags & UV_HANDLE_READING) {
uv__set_artificial_error(loop, UV_EALREADY);
if (handle->flags & UV_HANDLE_READING) {
uv__set_artificial_error(loop, UV_EISCONN);
return -1;
}
@ -773,6 +791,7 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
}
handle->flags |= UV_HANDLE_LISTENING;
INCREASE_ACTIVE_COUNT(loop, handle);
handle->connection_cb = cb;
/* First pipe handle should have already been created in uv_pipe_bind */
@ -955,17 +974,13 @@ static int uv_pipe_read_start_impl(uv_pipe_t* handle, uv_alloc_cb alloc_cb,
return -1;
}
if (handle->flags & UV_HANDLE_READING) {
uv__set_artificial_error(loop, UV_EALREADY);
return -1;
}
if (handle->flags & UV_HANDLE_EOF) {
uv__set_artificial_error(loop, UV_EOF);
return -1;
}
handle->flags |= UV_HANDLE_READING;
INCREASE_ACTIVE_COUNT(loop, handle);
handle->read_cb = read_cb;
handle->read2_cb = read2_cb;
handle->alloc_cb = alloc_cb;
@ -1154,10 +1169,10 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req,
/* Request queued by the kernel. */
ipc_header_req->queued_bytes = ipc_frame.header.flags & UV_IPC_TCP_SERVER ?
sizeof(ipc_frame) : sizeof(ipc_frame.header);
handle->write_queue_size += req->queued_bytes;
handle->write_queue_size += ipc_header_req->queued_bytes;
}
uv_ref(loop);
REGISTER_HANDLE_REQ(loop, handle, ipc_header_req);
handle->reqs_pending++;
handle->write_reqs_pending++;
@ -1212,7 +1227,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req,
}
}
uv_ref(loop);
REGISTER_HANDLE_REQ(loop, handle, req);
handle->reqs_pending++;
handle->write_reqs_pending++;
@ -1435,6 +1450,8 @@ void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,
assert(handle->write_queue_size >= req->queued_bytes);
handle->write_queue_size -= req->queued_bytes;
UNREGISTER_HANDLE_REQ(loop, handle, req);
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
if (req->wait_handle != INVALID_HANDLE_VALUE) {
UnregisterWait(req->wait_handle);
@ -1476,7 +1493,6 @@ void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,
uv_want_endgame(loop, (uv_handle_t*)handle);
}
uv_unref(loop);
DECREASE_PENDING_REQ_COUNT(handle);
}
@ -1513,6 +1529,8 @@ void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle,
uv_connect_t* req) {
assert(handle->type == UV_NAMED_PIPE);
UNREGISTER_HANDLE_REQ(loop, handle, req);
if (req->cb) {
if (REQ_SUCCESS(req)) {
uv_pipe_connection_init(handle);
@ -1523,7 +1541,6 @@ void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle,
}
}
uv_unref(loop);
DECREASE_PENDING_REQ_COUNT(handle);
}
@ -1532,6 +1549,8 @@ void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
uv_shutdown_t* req) {
assert(handle->type == UV_NAMED_PIPE);
UNREGISTER_HANDLE_REQ(loop, handle, req);
/* Initialize and optionally start the eof timer. */
/* This makes no sense if we've already seen EOF. */
if (!(handle->flags & UV_HANDLE_EOF)) {
@ -1548,7 +1567,6 @@ void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
req->cb(req, 0);
}
uv_unref(loop);
DECREASE_PENDING_REQ_COUNT(handle);
}
@ -1564,7 +1582,7 @@ static void eof_timer_init(uv_pipe_t* pipe) {
r = uv_timer_init(pipe->loop, pipe->eof_timer);
assert(r == 0); /* timers can't fail */
pipe->eof_timer->data = pipe;
uv_unref(pipe->loop);
uv_unref((uv_handle_t*) pipe->eof_timer);
}
@ -1598,7 +1616,7 @@ static void eof_timer_cb(uv_timer_t* timer, int status) {
/* or in uv_process_pipe_shutdown_req if a read is pending, */
/* and we always immediately stop the timer in */
/* uv_process_pipe_read_req. */
assert(pipe->flags & UV_HANDLE_READ_PENDING) ;
assert(pipe->flags & UV_HANDLE_READ_PENDING);
/* If there are many packets coming off the iocp then the timer callback */
/* may be called before the read request is coming off the queue. */
@ -1627,7 +1645,6 @@ static void eof_timer_destroy(uv_pipe_t* pipe) {
assert(pipe->flags && UV_HANDLE_CONNECTION);
if (pipe->eof_timer) {
uv_ref(pipe->loop);
uv_close((uv_handle_t*) pipe->eof_timer, eof_timer_close_cb);
pipe->eof_timer = NULL;
}

View File

@ -20,13 +20,12 @@
*/
#include "uv.h"
#include "internal.h"
#include <assert.h>
#include <io.h>
#include "uv.h"
#include "../uv-common.h"
#include "internal.h"
static const GUID uv_msafd_provider_ids[UV_MSAFD_PROVIDER_COUNT] = {
{0xe70f1aa0, 0xab8b, 0x11cf,
@ -202,6 +201,13 @@ static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0);
handle->events = events;
if (handle->events != 0) {
uv__handle_start(handle);
} else {
uv__handle_stop(handle);
}
if ((handle->events & ~(handle->submitted_events_1 |
handle->submitted_events_2)) != 0) {
uv__fast_poll_submit_poll_req(handle->loop, handle);
@ -213,6 +219,7 @@ static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
static void uv__fast_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
handle->events = 0;
uv__handle_start(handle);
if (handle->submitted_events_1 == 0 &&
handle->submitted_events_2 == 0) {
@ -449,6 +456,13 @@ static int uv__slow_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0);
handle->events = events;
if (handle->events != 0) {
uv__handle_start(handle);
} else {
uv__handle_stop(handle);
}
if ((handle->events &
~(handle->submitted_events_1 | handle->submitted_events_2)) != 0) {
uv__slow_poll_submit_poll_req(handle->loop, handle);
@ -460,6 +474,7 @@ static int uv__slow_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
static void uv__slow_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
handle->events = 0;
uv__handle_start(handle);
if (handle->submitted_events_1 == 0 &&
handle->submitted_events_2 == 0) {
@ -501,10 +516,9 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
socket = base_socket;
}
uv_handle_init(loop, (uv_handle_t*) handle);
handle->type = UV_POLL;
handle->socket = socket;
handle->loop = loop;
handle->flags = 0;
handle->events = 0;
/* Obtain protocol information about the socket. */
@ -542,9 +556,6 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
handle->poll_req_2.type = UV_POLL_REQ;
handle->poll_req_2.data = handle;
uv_ref(loop);
loop->counters.handle_init++;
loop->counters.poll_init++;
return 0;
@ -561,6 +572,7 @@ int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb) {
}
handle->poll_cb = cb;
return 0;
}
@ -600,10 +612,9 @@ void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) {
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_unref(loop);
}

View File

@ -20,7 +20,6 @@
*/
#include "uv.h"
#include "../uv-common.h"
#include "internal.h"
#include <stdio.h>
@ -55,9 +54,8 @@ typedef struct env_var {
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;
handle->loop = loop;
handle->flags = 0;
handle->exit_cb = NULL;
handle->pid = 0;
handle->exit_signal = 0;
@ -77,8 +75,6 @@ static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) {
loop->counters.handle_init++;
loop->counters.process_init++;
uv_ref(loop);
}
@ -689,29 +685,27 @@ static void close_child_stdio(uv_process_t* process) {
void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
DWORD exit_code;
/* FIXME: race condition. */
if (handle->flags & UV_HANDLE_CLOSING) {
return;
}
/* Unregister from process notification. */
if (handle->wait_handle != INVALID_HANDLE_VALUE) {
UnregisterWait(handle->wait_handle);
handle->wait_handle = INVALID_HANDLE_VALUE;
}
if (handle->process_handle != INVALID_HANDLE_VALUE) {
/* Get the exit code. */
if (!GetExitCodeProcess(handle->process_handle, &exit_code)) {
if (handle->process_handle == INVALID_HANDLE_VALUE ||
!GetExitCodeProcess(handle->process_handle, &exit_code)) {
/* The process never even started in the first place, or we were unable */
/* to obtain the exit code. */
exit_code = 127;
}
/* Clean-up the process handle. */
CloseHandle(handle->process_handle);
handle->process_handle = INVALID_HANDLE_VALUE;
} else {
/* We probably left the child stdio handles open to report the error */
/* asynchronously, so close them now. */
close_child_stdio(handle);
/* The process never even started in the first place. */
exit_code = 127;
}
/* Set the handle to inactive: no callbacks will be made after the exit */
/* callback.*/
uv__handle_stop(handle);
/* Fire the exit callback. */
if (handle->exit_cb) {
@ -726,21 +720,9 @@ void uv_process_proc_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;
if (handle->close_cb) {
handle->close_cb((uv_handle_t*)handle);
}
uv_unref(loop);
}
}
void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
uv__handle_start(handle);
if (handle->wait_handle != INVALID_HANDLE_VALUE) {
handle->close_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
UnregisterWaitEx(handle->wait_handle, handle->close_handle);
@ -755,6 +737,25 @@ 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);
}
}
}
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) {
@ -816,7 +817,7 @@ static int uv_create_stdio_pipe_pair(uv_loop_t* loop, uv_pipe_t* server_pipe,
done:
if (err) {
if (server_pipe->handle != INVALID_HANDLE_VALUE) {
close_pipe(server_pipe, NULL, NULL);
uv_pipe_cleanup(loop, server_pipe);
}
if (*child_pipe != INVALID_HANDLE_VALUE) {
@ -1058,7 +1059,12 @@ done:
}
}
if (err) {
if (err == 0) {
/* Spawn was succesful. The handle will be active until the exit */
/* is made or the handle is closed, whichever happens first. */
uv__handle_start(process);
} else {
/* Spawn was not successful. Clean up. */
if (process->wait_handle != INVALID_HANDLE_VALUE) {
UnregisterWait(process->wait_handle);
process->wait_handle = INVALID_HANDLE_VALUE;

View File

@ -22,7 +22,6 @@
#include <assert.h>
#include "uv.h"
#include "../uv-common.h"
#include "internal.h"
@ -147,8 +146,8 @@ void uv_process_reqs(uv_loop_t* loop) {
uv_process_ares_cleanup_req(loop, (uv_ares_task_t*) req->data, req);
break;
case UV_GETADDRINFO_REQ:
uv_process_getaddrinfo_req(loop, (uv_getaddrinfo_t*) req->data, req);
case UV_GETADDRINFO:
uv_process_getaddrinfo_req(loop, (uv_getaddrinfo_t*) req);
break;
case UV_PROCESS_EXIT:

View File

@ -22,19 +22,15 @@
#include <assert.h>
#include "uv.h"
#include "../uv-common.h"
#include "internal.h"
void uv_stream_init(uv_loop_t* loop, uv_stream_t* handle) {
uv_handle_init(loop, (uv_handle_t*) handle);
handle->write_queue_size = 0;
handle->loop = loop;
handle->flags = 0;
handle->activecnt = 0;
loop->counters.handle_init++;
loop->counters.stream_init++;
uv_ref(loop);
}
@ -109,8 +105,11 @@ int uv_read2_start(uv_stream_t* handle, uv_alloc_cb alloc_cb,
int uv_read_stop(uv_stream_t* handle) {
if (handle->type == UV_TTY) {
return uv_tty_read_stop((uv_tty_t*) handle);
} else {
} else if (handle->flags & UV_HANDLE_READING) {
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(handle->loop, handle);
return 0;
} else {
return 0;
}
}
@ -171,7 +170,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) {
handle->flags |= UV_HANDLE_SHUTTING;
handle->shutdown_req = req;
handle->reqs_pending++;
uv_ref(loop);
REGISTER_HANDLE_REQ(loop, handle, req);
uv_want_endgame(loop, (uv_handle_t*)handle);

View File

@ -22,7 +22,6 @@
#include <assert.h>
#include "uv.h"
#include "../uv-common.h"
#include "internal.h"
@ -143,12 +142,12 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) {
uv_stream_init(loop, (uv_stream_t*)handle);
uv_stream_init(loop, (uv_stream_t*) handle);
handle->type = UV_TCP;
handle->accept_reqs = NULL;
handle->pending_accepts = NULL;
handle->socket = INVALID_SOCKET;
handle->type = UV_TCP;
handle->reqs_pending = 0;
handle->func_acceptex = NULL;
handle->func_connectex = NULL;
@ -170,6 +169,8 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
handle->shutdown_req != NULL &&
handle->write_reqs_pending == 0) {
UNREGISTER_HANDLE_REQ(loop, handle, handle->shutdown_req);
if (handle->flags & UV_HANDLE_CLOSING) {
status = -1;
sys_error = WSAEINTR;
@ -180,6 +181,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
status = -1;
sys_error = WSAGetLastError();
}
if (handle->shutdown_req->cb) {
if (status == -1) {
uv__set_sys_error(loop, sys_error);
@ -188,8 +190,6 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
}
handle->shutdown_req = NULL;
uv_unref(loop);
DECREASE_PENDING_REQ_COUNT(handle);
return;
}
@ -198,6 +198,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
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)) {
closesocket(handle->socket);
@ -240,8 +241,6 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
}
loop->active_tcp_streams--;
uv_unref(loop);
}
}
@ -500,6 +499,15 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
assert(backlog > 0);
if (handle->flags & UV_HANDLE_LISTENING) {
handle->connection_cb = cb;
}
if (handle->flags & UV_HANDLE_READING) {
uv__set_artificial_error(loop, UV_EISCONN);
return -1;
}
if (handle->flags & UV_HANDLE_BIND_ERROR) {
uv__set_sys_error(loop, handle->bind_error);
return -1;
@ -524,6 +532,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
handle->flags |= UV_HANDLE_LISTENING;
handle->connection_cb = cb;
INCREASE_ACTIVE_COUNT(loop, handle);
simultaneous_accepts = handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT ? 1
: uv_simultaneous_server_accepts;
@ -642,6 +651,7 @@ int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
handle->flags |= UV_HANDLE_READING;
handle->read_cb = read_cb;
handle->alloc_cb = alloc_cb;
INCREASE_ACTIVE_COUNT(loop, handle);
/* If reading was stopped and then started again, there could still be a */
/* read request pending. */
@ -702,12 +712,12 @@ int uv__tcp_connect(uv_connect_t* req,
if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
/* Process the req without IOCP. */
handle->reqs_pending++;
uv_ref(loop);
REGISTER_HANDLE_REQ(loop, handle, req);
uv_insert_pending_req(loop, (uv_req_t*)req);
} else if (UV_SUCCEEDED_WITH_IOCP(success)) {
/* The req will be processed with IOCP. */
handle->reqs_pending++;
uv_ref(loop);
REGISTER_HANDLE_REQ(loop, handle, req);
} else {
uv__set_sys_error(loop, WSAGetLastError());
return -1;
@ -763,11 +773,11 @@ int uv__tcp_connect6(uv_connect_t* req,
if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
handle->reqs_pending++;
uv_ref(loop);
REGISTER_HANDLE_REQ(loop, handle, req);
uv_insert_pending_req(loop, (uv_req_t*)req);
} else if (UV_SUCCEEDED_WITH_IOCP(success)) {
handle->reqs_pending++;
uv_ref(loop);
REGISTER_HANDLE_REQ(loop, handle, req);
} else {
uv__set_sys_error(loop, WSAGetLastError());
return -1;
@ -872,15 +882,15 @@ int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle,
req->queued_bytes = 0;
handle->reqs_pending++;
handle->write_reqs_pending++;
REGISTER_HANDLE_REQ(loop, handle, req);
uv_insert_pending_req(loop, (uv_req_t*) req);
uv_ref(loop);
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
/* Request queued by the kernel. */
req->queued_bytes = uv_count_bufs(bufs, bufcnt);
handle->reqs_pending++;
handle->write_reqs_pending++;
REGISTER_HANDLE_REQ(loop, handle, req);
handle->write_queue_size += req->queued_bytes;
uv_ref(loop);
if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
!RegisterWaitForSingleObject(&req->wait_handle,
req->event_handle, post_write_completion, (void*) req,
@ -912,6 +922,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
if ((handle->flags & UV_HANDLE_READING) ||
!(handle->flags & UV_HANDLE_ZERO_READ)) {
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, handle);
buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
uv_buf_init(NULL, 0) : handle->read_buffer;
@ -942,8 +953,12 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
}
} else {
/* Connection closed */
if (handle->flags & UV_HANDLE_READING) {
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, handle);
}
handle->flags |= UV_HANDLE_EOF;
uv__set_error(loop, UV_EOF, ERROR_SUCCESS);
buf.base = 0;
buf.len = 0;
@ -974,7 +989,9 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
} else {
/* Connection closed */
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, handle);
handle->flags |= UV_HANDLE_EOF;
uv__set_error(loop, UV_EOF, ERROR_SUCCESS);
handle->read_cb((uv_stream_t*)handle, -1, buf);
break;
@ -986,16 +1003,18 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
uv__set_sys_error(loop, WSAEWOULDBLOCK);
handle->read_cb((uv_stream_t*)handle, 0, buf);
} else {
/* Ouch! serious error. */
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, handle);
if (err == WSAECONNABORTED) {
/*
* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix.
*/
/* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with */
/* Unix. */
uv__set_error(loop, UV_ECONNRESET, err);
} else {
/* Ouch! serious error. */
uv__set_sys_error(loop, err);
}
handle->flags &= ~UV_HANDLE_READING;
handle->read_cb((uv_stream_t*)handle, -1, buf);
}
break;
@ -1021,6 +1040,8 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
assert(handle->write_queue_size >= req->queued_bytes);
handle->write_queue_size -= req->queued_bytes;
UNREGISTER_HANDLE_REQ(loop, handle, req);
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
if (req->wait_handle != INVALID_HANDLE_VALUE) {
UnregisterWait(req->wait_handle);
@ -1042,7 +1063,6 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
}
DECREASE_PENDING_REQ_COUNT(handle);
uv_unref(loop);
}
@ -1059,6 +1079,7 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
if (req->accept_socket == INVALID_SOCKET) {
if (handle->flags & UV_HANDLE_LISTENING) {
handle->flags &= ~UV_HANDLE_LISTENING;
DECREASE_ACTIVE_COUNT(loop, handle);
if (handle->connection_cb) {
uv__set_sys_error(loop, GET_REQ_SOCK_ERROR(req));
handle->connection_cb((uv_stream_t*)handle, -1);
@ -1096,7 +1117,8 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
uv_connect_t* req) {
assert(handle->type == UV_TCP);
if (req->cb) {
UNREGISTER_HANDLE_REQ(loop, handle, req);
if (REQ_SUCCESS(req)) {
if (setsockopt(handle->socket,
SOL_SOCKET,
@ -1114,10 +1136,8 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
uv__set_sys_error(loop, GET_REQ_SOCK_ERROR(req));
((uv_connect_cb)req->cb)(req, -1);
}
}
DECREASE_PENDING_REQ_COUNT(handle);
uv_unref(loop);
}
@ -1189,7 +1209,6 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {
}
int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid,
LPWSAPROTOCOL_INFOW protocol_info) {
if (!(handle->flags & UV_HANDLE_CONNECTION)) {
@ -1257,7 +1276,7 @@ int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
}
void uv_tcp_close(uv_tcp_t* tcp) {
void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
int non_ifs_lsp;
int close_socket = 1;
@ -1286,13 +1305,23 @@ void uv_tcp_close(uv_tcp_t* tcp) {
}
}
tcp->flags &= ~(UV_HANDLE_READING | UV_HANDLE_LISTENING);
if (tcp->flags & UV_HANDLE_READING) {
tcp->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, tcp);
}
if (tcp->flags & UV_HANDLE_LISTENING) {
tcp->flags &= ~UV_HANDLE_LISTENING;
DECREASE_ACTIVE_COUNT(loop, tcp);
}
if (close_socket) {
closesocket(tcp->socket);
tcp->flags |= UV_HANDLE_TCP_SOCKET_CLOSED;
}
uv__handle_start(tcp);
if (tcp->reqs_pending == 0) {
uv_want_endgame(tcp->loop, (uv_handle_t*)tcp);
}

View File

@ -19,11 +19,12 @@
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "../uv-common.h"
#include "internal.h"
#include <assert.h>
#include "uv.h"
#include "internal.h"
#define HAVE_SRWLOCK_API() (pTryAcquireSRWLockShared != NULL)
#ifdef _MSC_VER /* msvc */

View File

@ -61,13 +61,13 @@ int uv_queue_work(uv_loop_t* loop, uv_work_t* req, uv_work_cb work_cb,
return -1;
}
uv_ref(loop);
uv__req_register(loop, req);
return 0;
}
void uv_process_work_req(uv_loop_t* loop, uv_work_t* req) {
assert(req->after_work_cb);
uv__req_unregister(loop, req);
req->after_work_cb(req);
uv_unref(loop);
}

View File

@ -26,6 +26,7 @@
#include "internal.h"
#include "tree.h"
#undef NANOSEC
#define NANOSEC 1000000000
@ -111,16 +112,12 @@ RB_GENERATE_STATIC(uv_timer_tree_s, uv_timer_s, tree_entry, uv_timer_compare);
int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
loop->counters.handle_init++;
loop->counters.timer_init++;
uv_handle_init(loop, (uv_handle_t*) handle);
handle->type = UV_TIMER;
handle->loop = loop;
handle->flags = 0;
handle->timer_cb = NULL;
handle->repeat = 0;
uv_ref(loop);
loop->counters.timer_init++;
return 0;
}
@ -130,12 +127,11 @@ 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_unref(loop);
}
}
@ -152,6 +148,7 @@ int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, int64_t timeout,
handle->due = loop->time + timeout;
handle->repeat = repeat;
handle->flags |= UV_HANDLE_ACTIVE;
uv__handle_start(handle);
if (RB_INSERT(uv_timer_tree_s, &loop->timers, handle) != NULL) {
uv_fatal_error(ERROR_INVALID_DATA, "RB_INSERT");
@ -170,6 +167,7 @@ int uv_timer_stop(uv_timer_t* handle) {
RB_REMOVE(uv_timer_tree_s, &loop->timers, handle);
handle->flags &= ~UV_HANDLE_ACTIVE;
uv__handle_stop(handle);
return 0;
}
@ -187,6 +185,7 @@ int uv_timer_again(uv_timer_t* handle) {
if (handle->flags & UV_HANDLE_ACTIVE) {
RB_REMOVE(uv_timer_tree_s, &loop->timers, handle);
handle->flags &= ~UV_HANDLE_ACTIVE;
uv__handle_stop(handle);
}
if (handle->repeat) {
@ -197,6 +196,7 @@ int uv_timer_again(uv_timer_t* handle) {
}
handle->flags |= UV_HANDLE_ACTIVE;
uv__handle_start(handle);
}
return 0;
@ -268,6 +268,7 @@ void uv_process_timers(uv_loop_t* loop) {
} else {
/* If non-repeating, mark the timer as inactive. */
timer->flags &= ~UV_HANDLE_ACTIVE;
uv__handle_stop(timer);
}
timer->timer_cb((uv_timer_t*) timer, 0);

View File

@ -25,7 +25,6 @@
#include <stdint.h>
#include "uv.h"
#include "../uv-common.h"
#include "internal.h"
@ -462,8 +461,9 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
/* Fetch the number of events */
if (!GetNumberOfConsoleInputEvents(handle->handle, &records_left)) {
handle->flags &= ~UV_HANDLE_READING;
uv__set_sys_error(loop, GetLastError());
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, handle);
handle->read_cb((uv_stream_t*)handle, -1, uv_null_buf_);
goto out;
}
@ -483,6 +483,7 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
&records_read)) {
uv__set_sys_error(loop, GetLastError());
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, handle);
handle->read_cb((uv_stream_t*) handle, -1, buf);
goto out;
}
@ -583,6 +584,7 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
if (!char_len) {
uv__set_sys_error(loop, GetLastError());
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, handle);
handle->read_cb((uv_stream_t*) handle, -1, buf);
goto out;
}
@ -691,6 +693,7 @@ void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle,
!(handle->flags & UV_HANDLE_TTY_RAW)) {
/* Real error */
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, handle);
uv__set_sys_error(loop, GET_REQ_ERROR(req));
handle->read_cb((uv_stream_t*) handle, -1, buf);
} else {
@ -738,6 +741,7 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
uv_loop_t* loop = handle->loop;
handle->flags |= UV_HANDLE_READING;
INCREASE_ACTIVE_COUNT(loop, handle);
handle->read_cb = read_cb;
handle->alloc_cb = alloc_cb;
@ -762,7 +766,12 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
int uv_tty_read_stop(uv_tty_t* handle) {
uv_loop_t* loop = handle->loop;
if (handle->flags & UV_HANDLE_READING) {
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, handle);
}
/* Cancel raw read */
if ((handle->flags & UV_HANDLE_READ_PENDING) &&
@ -772,7 +781,7 @@ int uv_tty_read_stop(uv_tty_t* handle) {
DWORD written;
memset(&record, 0, sizeof record);
if (!WriteConsoleInputW(handle->handle, &record, 1, &written)) {
uv__set_sys_error(handle->loop, GetLastError());
uv__set_sys_error(loop, GetLastError());
return -1;
}
}
@ -1680,7 +1689,7 @@ int uv_tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle,
handle->reqs_pending++;
handle->write_reqs_pending++;
uv_ref(loop);
REGISTER_HANDLE_REQ(loop, handle, req);
req->queued_bytes = 0;
@ -1700,6 +1709,7 @@ void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
uv_write_t* req) {
handle->write_queue_size -= req->queued_bytes;
UNREGISTER_HANDLE_REQ(loop, handle, req);
if (req->cb) {
uv__set_sys_error(loop, GET_REQ_ERROR(req));
@ -1713,7 +1723,6 @@ void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
}
DECREASE_PENDING_REQ_COUNT(handle);
uv_unref(loop);
}
@ -1723,6 +1732,8 @@ void uv_tty_close(uv_tty_t* handle) {
uv_tty_read_stop(handle);
CloseHandle(handle->handle);
uv__handle_start(handle);
if (handle->reqs_pending == 0) {
uv_want_endgame(handle->loop, (uv_handle_t*) handle);
}
@ -1733,6 +1744,8 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
if ((handle->flags && UV_HANDLE_CONNECTION) &&
handle->shutdown_req != NULL &&
handle->write_reqs_pending == 0) {
UNREGISTER_HANDLE_REQ(loop, handle, handle->shutdown_req);
/* TTY shutdown is really just a no-op */
if (handle->shutdown_req->cb) {
if (handle->flags & UV_HANDLE_CLOSING) {
@ -1745,7 +1758,6 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
handle->shutdown_req = NULL;
uv_unref(loop);
DECREASE_PENDING_REQ_COUNT(handle);
return;
}
@ -1762,12 +1774,11 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
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_unref(loop);
}
}

View File

@ -22,7 +22,6 @@
#include <assert.h>
#include "uv.h"
#include "../uv-common.h"
#include "internal.h"
@ -121,11 +120,12 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle,
int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
uv_handle_init(loop, (uv_handle_t*) handle);
handle->type = UV_UDP;
handle->socket = INVALID_SOCKET;
handle->reqs_pending = 0;
handle->loop = loop;
handle->flags = 0;
handle->activecnt = 0;
handle->func_wsarecv = WSARecv;
handle->func_wsarecvfrom = WSARecvFrom;
@ -133,26 +133,34 @@ int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
handle->recv_req.type = UV_UDP_RECV;
handle->recv_req.data = handle;
uv_ref(loop);
loop->counters.handle_init++;
loop->counters.udp_init++;
return 0;
}
void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) {
uv_udp_recv_stop(handle);
closesocket(handle->socket);
uv__handle_start(handle);
if (handle->reqs_pending == 0) {
uv_want_endgame(loop, (uv_handle_t*) handle);
}
}
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_unref(loop);
}
}
@ -350,6 +358,7 @@ int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
}
handle->flags |= UV_HANDLE_READING;
INCREASE_ACTIVE_COUNT(loop, handle);
loop->active_udp_streams++;
handle->recv_cb = recv_cb;
@ -368,6 +377,7 @@ int uv_udp_recv_stop(uv_udp_t* handle) {
if (handle->flags & UV_HANDLE_READING) {
handle->flags &= ~UV_HANDLE_READING;
handle->loop->active_udp_streams--;
DECREASE_ACTIVE_COUNT(loop, handle);
}
return 0;
@ -399,13 +409,13 @@ static int uv__udp_send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[],
/* Request completed immediately. */
req->queued_bytes = 0;
handle->reqs_pending++;
uv_ref(loop);
REGISTER_HANDLE_REQ(loop, handle, req);
uv_insert_pending_req(loop, (uv_req_t*)req);
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
/* Request queued by the kernel. */
req->queued_bytes = uv_count_bufs(bufs, bufcnt);
handle->reqs_pending++;
uv_ref(loop);
REGISTER_HANDLE_REQ(loop, handle, req);
} else {
/* Send failed due to an error. */
uv__set_sys_error(loop, WSAGetLastError());
@ -561,6 +571,8 @@ void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
uv_udp_send_t* req) {
assert(handle->type == UV_UDP);
UNREGISTER_HANDLE_REQ(loop, handle, req);
if (req->cb) {
if (REQ_SUCCESS(req)) {
req->cb(req, 0);
@ -570,7 +582,6 @@ void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
}
}
uv_unref(loop);
DECREASE_PENDING_REQ_COUNT(handle);
}

View File

@ -29,9 +29,10 @@
#include "uv.h"
#include "internal.h"
#include "tlhelp32.h"
#include "psapi.h"
#include "iphlpapi.h"
#include <iphlpapi.h>
#include <psapi.h>
#include <tlhelp32.h>
/*

View File

@ -22,7 +22,6 @@
#include <assert.h>
#include "uv.h"
#include "../uv-common.h"
#include "internal.h"

View File

@ -22,9 +22,9 @@
#include <assert.h>
#include "uv.h"
#include "../uv-common.h"
#include "internal.h"
/* Whether ipv6 is supported */
int uv_allow_ipv6;

View File

@ -144,7 +144,7 @@ static int do_packet_storm(int n_senders, int n_receivers) {
ASSERT(r == 0);
/* Timer should not keep loop alive. */
uv_unref(loop);
uv_unref((uv_handle_t*)&timeout);
for (i = 0; i < n_receivers; i++) {
struct sockaddr_in addr;

View File

@ -68,7 +68,6 @@ void idle_cb(uv_idle_t* idle, int status) {
int r;
r = uv_idle_stop(idle);
uv_unref(uv_default_loop());
ASSERT(r == 0);
}
}

View File

@ -89,7 +89,6 @@ TEST_DECLARE (tcp_ref)
TEST_DECLARE (tcp_ref2)
TEST_DECLARE (tcp_ref3)
TEST_DECLARE (tcp_ref4)
TEST_DECLARE (tcp_ref5)
TEST_DECLARE (udp_ref)
TEST_DECLARE (udp_ref2)
TEST_DECLARE (udp_ref3)
@ -97,7 +96,6 @@ TEST_DECLARE (pipe_ref)
TEST_DECLARE (pipe_ref2)
TEST_DECLARE (pipe_ref3)
TEST_DECLARE (pipe_ref4)
TEST_DECLARE (pipe_ref5)
TEST_DECLARE (process_ref)
TEST_DECLARE (async)
TEST_DECLARE (get_currentexe)
@ -275,8 +273,6 @@ TASK_LIST_START
TEST_HELPER (tcp_ref3, tcp4_echo_server)
TEST_ENTRY (tcp_ref4)
TEST_HELPER (tcp_ref4, tcp4_echo_server)
TEST_ENTRY (tcp_ref5)
TEST_HELPER (tcp_ref5, tcp4_echo_server)
TEST_ENTRY (udp_ref)
TEST_ENTRY (udp_ref2)
TEST_ENTRY (udp_ref3)
@ -287,8 +283,6 @@ TASK_LIST_START
TEST_HELPER (pipe_ref3, pipe_echo_server)
TEST_ENTRY (pipe_ref4)
TEST_HELPER (pipe_ref4, pipe_echo_server)
TEST_ENTRY (pipe_ref5)
TEST_HELPER (pipe_ref5, pipe_echo_server)
TEST_ENTRY (process_ref)
TEST_ENTRY (loop_handles)

View File

@ -323,7 +323,7 @@ TEST_IMPL(loop_handles) {
ASSERT(r == 0);
r = uv_timer_start(&timer_handle, timer_cb, TIMEOUT, TIMEOUT);
ASSERT(r == 0);
uv_unref(uv_default_loop());
uv_unref((uv_handle_t*)&timer_handle);
r = uv_run(uv_default_loop());
ASSERT(r == 0);

View File

@ -32,30 +32,50 @@ static uv_connect_t connect_req;
static char buffer[32767];
static int req_cb_called;
static int connect_cb_called;
static int write_cb_called;
static int shutdown_cb_called;
static void fail_cb(void) {
FATAL("fail_cb should not have been called");
}
static void write_unref_cb(uv_connect_t* req, int status) {
uv_buf_t buf = uv_buf_init(buffer, sizeof buffer);
static void req_cb(uv_handle_t* req, int status) {
req_cb_called++;
}
static void shutdown_cb(uv_shutdown_t* req, int status) {
ASSERT(req == &shutdown_req);
shutdown_cb_called++;
}
static void write_cb(uv_write_t* req, int status) {
ASSERT(req == &write_req);
uv_shutdown(&shutdown_req, req->handle, shutdown_cb);
write_cb_called++;
}
static void connect_and_write(uv_connect_t* req, int status) {
uv_buf_t buf = uv_buf_init(buffer, sizeof buffer);
ASSERT(req == &connect_req);
ASSERT(status == 0);
uv_write(&write_req, req->handle, &buf, 1, (uv_write_cb) fail_cb);
uv_unref(uv_default_loop()); /* uv_write refs the loop */
uv_write(&write_req, req->handle, &buf, 1, write_cb);
connect_cb_called++;
}
static void shutdown_unref_cb(uv_connect_t* req, int status) {
static void connect_and_shutdown(uv_connect_t* req, int status) {
ASSERT(req == &connect_req);
ASSERT(status == 0);
uv_shutdown(&shutdown_req, req->handle, (uv_shutdown_cb) fail_cb);
uv_unref(uv_default_loop()); /* uv_shutdown refs the loop */
uv_shutdown(&shutdown_req, req->handle, shutdown_cb);
connect_cb_called++;
}
@ -69,7 +89,7 @@ TEST_IMPL(idle_ref) {
uv_idle_t h;
uv_idle_init(uv_default_loop(), &h);
uv_idle_start(&h, NULL);
uv_unref(uv_default_loop());
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
return 0;
}
@ -78,7 +98,7 @@ TEST_IMPL(idle_ref) {
TEST_IMPL(async_ref) {
uv_async_t h;
uv_async_init(uv_default_loop(), &h, NULL);
uv_unref(uv_default_loop());
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
return 0;
}
@ -88,7 +108,7 @@ TEST_IMPL(prepare_ref) {
uv_prepare_t h;
uv_prepare_init(uv_default_loop(), &h);
uv_prepare_start(&h, NULL);
uv_unref(uv_default_loop());
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
return 0;
}
@ -98,17 +118,16 @@ TEST_IMPL(check_ref) {
uv_check_t h;
uv_check_init(uv_default_loop(), &h);
uv_check_start(&h, NULL);
uv_unref(uv_default_loop());
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
return 0;
}
static void prepare_cb(uv_prepare_t* handle, int status) {
ASSERT(handle != NULL);
static void prepare_cb(uv_prepare_t* h, int status) {
ASSERT(h != NULL);
ASSERT(status == 0);
uv_unref(uv_default_loop());
uv_unref((uv_handle_t*)h);
}
@ -124,7 +143,7 @@ TEST_IMPL(unref_in_prepare_cb) {
TEST_IMPL(timer_ref) {
uv_timer_t h;
uv_timer_init(uv_default_loop(), &h);
uv_unref(uv_default_loop());
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
return 0;
}
@ -133,8 +152,8 @@ TEST_IMPL(timer_ref) {
TEST_IMPL(timer_ref2) {
uv_timer_t h;
uv_timer_init(uv_default_loop(), &h);
uv_timer_start(&h, (uv_timer_cb) fail_cb, 42, 42);
uv_unref(uv_default_loop());
uv_timer_start(&h, (uv_timer_cb)fail_cb, 42, 42);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
return 0;
}
@ -142,8 +161,8 @@ TEST_IMPL(timer_ref2) {
TEST_IMPL(fs_event_ref) {
uv_fs_event_t h;
uv_fs_event_init(uv_default_loop(), &h, ".", (uv_fs_event_cb) fail_cb, 0);
uv_unref(uv_default_loop());
uv_fs_event_init(uv_default_loop(), &h, ".", (uv_fs_event_cb)fail_cb, 0);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
return 0;
}
@ -152,7 +171,7 @@ TEST_IMPL(fs_event_ref) {
TEST_IMPL(tcp_ref) {
uv_tcp_t h;
uv_tcp_init(uv_default_loop(), &h);
uv_unref(uv_default_loop());
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
return 0;
}
@ -162,7 +181,7 @@ TEST_IMPL(tcp_ref2) {
uv_tcp_t h;
uv_tcp_init(uv_default_loop(), &h);
uv_listen((uv_stream_t*)&h, 128, (uv_connection_cb)fail_cb);
uv_unref(uv_default_loop());
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
return 0;
}
@ -172,10 +191,11 @@ TEST_IMPL(tcp_ref3) {
struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
uv_tcp_t h;
uv_tcp_init(uv_default_loop(), &h);
uv_tcp_connect(&connect_req, &h, addr, (uv_connect_cb)fail_cb);
uv_unref(uv_default_loop());
uv_unref(uv_default_loop()); /* connect req refs the loop */
uv_tcp_connect(&connect_req, &h, addr, connect_and_shutdown);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
ASSERT(connect_cb_called == 1);
ASSERT(shutdown_cb_called == 1);
return 0;
}
@ -184,20 +204,12 @@ TEST_IMPL(tcp_ref4) {
struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
uv_tcp_t h;
uv_tcp_init(uv_default_loop(), &h);
uv_tcp_connect(&connect_req, &h, addr, write_unref_cb);
uv_unref(uv_default_loop());
uv_run(uv_default_loop());
return 0;
}
TEST_IMPL(tcp_ref5) {
struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
uv_tcp_t h;
uv_tcp_init(uv_default_loop(), &h);
uv_tcp_connect(&connect_req, &h, addr, shutdown_unref_cb);
uv_unref(uv_default_loop());
uv_tcp_connect(&connect_req, &h, addr, connect_and_write);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
ASSERT(connect_cb_called == 1);
ASSERT(write_cb_called == 1);
ASSERT(shutdown_cb_called == 1);
return 0;
}
@ -205,7 +217,7 @@ TEST_IMPL(tcp_ref5) {
TEST_IMPL(udp_ref) {
uv_udp_t h;
uv_udp_init(uv_default_loop(), &h);
uv_unref(uv_default_loop());
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
return 0;
}
@ -217,7 +229,7 @@ TEST_IMPL(udp_ref2) {
uv_udp_init(uv_default_loop(), &h);
uv_udp_bind(&h, addr, 0);
uv_udp_recv_start(&h, (uv_alloc_cb)fail_cb, (uv_udp_recv_cb)fail_cb);
uv_unref(uv_default_loop());
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
return 0;
}
@ -230,10 +242,10 @@ TEST_IMPL(udp_ref3) {
uv_udp_t h;
uv_udp_init(uv_default_loop(), &h);
uv_udp_send(&req, &h, &buf, 1, addr, (uv_udp_send_cb)fail_cb);
uv_unref(uv_default_loop());
uv_unref(uv_default_loop()); /* send req refs the loop */
uv_udp_send(&req, &h, &buf, 1, addr, (uv_udp_send_cb)req_cb);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
ASSERT(req_cb_called == 1);
return 0;
}
@ -242,7 +254,7 @@ TEST_IMPL(udp_ref3) {
TEST_IMPL(pipe_ref) {
uv_pipe_t h;
uv_pipe_init(uv_default_loop(), &h, 0);
uv_unref(uv_default_loop());
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
return 0;
}
@ -252,7 +264,7 @@ TEST_IMPL(pipe_ref2) {
uv_pipe_t h;
uv_pipe_init(uv_default_loop(), &h, 0);
uv_listen((uv_stream_t*)&h, 128, (uv_connection_cb)fail_cb);
uv_unref(uv_default_loop());
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
return 0;
}
@ -261,10 +273,11 @@ TEST_IMPL(pipe_ref2) {
TEST_IMPL(pipe_ref3) {
uv_pipe_t h;
uv_pipe_init(uv_default_loop(), &h, 0);
uv_pipe_connect(&connect_req, &h, TEST_PIPENAME, (uv_connect_cb)fail_cb);
uv_unref(uv_default_loop());
uv_unref(uv_default_loop()); /* connect req refs the loop */
uv_pipe_connect(&connect_req, &h, TEST_PIPENAME, connect_and_shutdown);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
ASSERT(connect_cb_called == 1);
ASSERT(shutdown_cb_called == 1);
return 0;
}
@ -272,19 +285,12 @@ TEST_IMPL(pipe_ref3) {
TEST_IMPL(pipe_ref4) {
uv_pipe_t h;
uv_pipe_init(uv_default_loop(), &h, 0);
uv_pipe_connect(&connect_req, &h, TEST_PIPENAME, write_unref_cb);
uv_unref(uv_default_loop());
uv_run(uv_default_loop());
return 0;
}
TEST_IMPL(pipe_ref5) {
uv_pipe_t h;
uv_pipe_init(uv_default_loop(), &h, 0);
uv_pipe_connect(&connect_req, &h, TEST_PIPENAME, shutdown_unref_cb);
uv_unref(uv_default_loop());
uv_pipe_connect(&connect_req, &h, TEST_PIPENAME, connect_and_write);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
ASSERT(connect_cb_called == 1);
ASSERT(write_cb_called == 1);
ASSERT(shutdown_cb_called == 1);
return 0;
}
@ -312,7 +318,7 @@ TEST_IMPL(process_ref) {
r = uv_spawn(uv_default_loop(), &h, options);
ASSERT(r == 0);
uv_unref(uv_default_loop());
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop());
r = uv_process_kill(&h, /* SIGTERM */ 15);

View File

@ -203,8 +203,8 @@ int stdio_over_pipes_helper() {
uv_pipe_open(&stdout_pipe, 1);
/* Unref both stdio handles to make sure that all writes complete. */
uv_unref(loop);
uv_unref(loop);
uv_unref((uv_handle_t*)&stdin_pipe);
uv_unref((uv_handle_t*)&stdout_pipe);
for (i = 0; i < ARRAY_SIZE(buffers); i++) {
buf[i] = uv_buf_init((char*)buffers[i], strlen(buffers[i]));
@ -222,8 +222,8 @@ int stdio_over_pipes_helper() {
ASSERT(on_pipe_read_called == 0);
ASSERT(close_cb_called == 0);
uv_ref(loop);
uv_ref(loop);
uv_ref((uv_handle_t*)&stdout_pipe);
uv_ref((uv_handle_t*)&stdin_pipe);
r = uv_read_start((uv_stream_t*)&stdin_pipe, on_read_alloc,
on_pipe_read);

View File

@ -88,7 +88,7 @@ static void start_server(uv_loop_t* loop, uv_tcp_t* handle) {
r = uv_listen((uv_stream_t*)handle, 128, connection_cb);
ASSERT(r == 0);
uv_unref(loop);
uv_unref((uv_handle_t*)handle);
}

View File

@ -104,7 +104,7 @@ TEST_IMPL(timer_again) {
r = uv_timer_again(&dummy);
ASSERT(r == -1);
ASSERT(uv_last_error(uv_default_loop()).code == UV_EINVAL);
uv_unref(uv_default_loop());
uv_unref((uv_handle_t*)&dummy);
/* Start timer repeat_1. */
r = uv_timer_init(uv_default_loop(), &repeat_1);

View File

@ -114,7 +114,7 @@ TEST_IMPL(timer) {
ASSERT(r == 0);
r = uv_timer_stop(&never);
ASSERT(r == 0);
uv_unref(uv_default_loop());
uv_unref((uv_handle_t*)&never);
uv_run(uv_default_loop());

View File

@ -38,7 +38,7 @@ TEST_IMPL(udp_options) {
r = uv_udp_init(loop, &h);
ASSERT(r == 0);
uv_unref(loop); /* don't keep the loop alive */
uv_unref((uv_handle_t*)&h); /* don't keep the loop alive */
r = uv_udp_bind(&h, uv_ip4_addr("0.0.0.0", TEST_PORT), 0);
ASSERT(r == 0);

7
uv.gyp
View File

@ -47,6 +47,8 @@
'include/ares.h',
'include/ares_version.h',
'include/uv.h',
'include/uv-private/ngx-queue.h',
'include/uv-private/tree.h',
'src/uv-common.c',
'src/uv-common.h',
'src/ares/ares_cancel.c',
@ -125,7 +127,6 @@
'_GNU_SOURCE',
],
'sources': [
'include/uv-private/tree.h',
'include/uv-private/uv-win.h',
'src/ares/config_win32/ares_config.h',
'src/ares/windows_port.c',
@ -179,11 +180,9 @@
'sources': [
'include/uv-private/eio.h',
'include/uv-private/ev.h',
'include/uv-private/ngx-queue.h',
'include/uv-private/uv-unix.h',
'src/unix/async.c',
'src/unix/cares.c',
'src/unix/check.c',
'src/unix/core.c',
'src/unix/dl.c',
'src/unix/eio/ecb.h',
@ -195,12 +194,10 @@
'src/unix/ev/ev_wrap.h',
'src/unix/ev/event.h',
'src/unix/fs.c',
'src/unix/idle.c',
'src/unix/internal.h',
'src/unix/loop.c',
'src/unix/pipe.c',
'src/unix/poll.c',
'src/unix/prepare.c',
'src/unix/process.c',
'src/unix/stream.c',
'src/unix/tcp.c',