aboutsummaryrefslogtreecommitdiff
path: root/deps/uv/src
diff options
context:
space:
mode:
Diffstat (limited to 'deps/uv/src')
-rw-r--r--deps/uv/src/unix/async.c6
-rw-r--r--deps/uv/src/unix/cares.c23
-rw-r--r--deps/uv/src/unix/check.c80
-rw-r--r--deps/uv/src/unix/core.c167
-rw-r--r--deps/uv/src/unix/dl.c79
-rw-r--r--deps/uv/src/unix/ev/ev.c1
-rw-r--r--deps/uv/src/unix/fs.c45
-rw-r--r--deps/uv/src/unix/idle.c79
-rw-r--r--deps/uv/src/unix/internal.h46
-rw-r--r--deps/uv/src/unix/kqueue.c4
-rw-r--r--deps/uv/src/unix/linux/inotify.c3
-rw-r--r--deps/uv/src/unix/loop.c59
-rw-r--r--deps/uv/src/unix/pipe.c18
-rw-r--r--deps/uv/src/unix/poll.c123
-rw-r--r--deps/uv/src/unix/prepare.c79
-rw-r--r--deps/uv/src/unix/process.c16
-rw-r--r--deps/uv/src/unix/stream.c125
-rw-r--r--deps/uv/src/unix/sunos.c50
-rw-r--r--deps/uv/src/unix/tcp.c6
-rw-r--r--deps/uv/src/unix/timer.c32
-rw-r--r--deps/uv/src/unix/tty.c4
-rw-r--r--deps/uv/src/unix/udp.c14
-rw-r--r--deps/uv/src/unix/uv-eio.c67
-rw-r--r--deps/uv/src/uv-common.c10
-rw-r--r--deps/uv/src/uv-common.h119
-rw-r--r--deps/uv/src/win/async.c22
-rw-r--r--deps/uv/src/win/cares.c8
-rw-r--r--deps/uv/src/win/core.c57
-rw-r--r--deps/uv/src/win/dl.c76
-rw-r--r--deps/uv/src/win/error.c1
-rw-r--r--deps/uv/src/win/fs-event.c36
-rw-r--r--deps/uv/src/win/fs.c405
-rw-r--r--deps/uv/src/win/getaddrinfo.c118
-rw-r--r--deps/uv/src/win/handle.c61
-rw-r--r--deps/uv/src/win/internal.h142
-rw-r--r--deps/uv/src/win/loop-watcher.c13
-rw-r--r--deps/uv/src/win/pipe.c93
-rw-r--r--deps/uv/src/win/poll.c620
-rw-r--r--deps/uv/src/win/process.c78
-rw-r--r--deps/uv/src/win/req.c9
-rw-r--r--deps/uv/src/win/stream.c15
-rw-r--r--deps/uv/src/win/tcp.c148
-rw-r--r--deps/uv/src/win/thread.c5
-rw-r--r--deps/uv/src/win/threadpool.c4
-rw-r--r--deps/uv/src/win/timer.c18
-rw-r--r--deps/uv/src/win/tty.c32
-rw-r--r--deps/uv/src/win/udp.c33
-rw-r--r--deps/uv/src/win/util.c7
-rw-r--r--deps/uv/src/win/winapi.c5
-rw-r--r--deps/uv/src/win/winapi.h9
-rw-r--r--deps/uv/src/win/winsock.c89
-rw-r--r--deps/uv/src/win/winsock.h39
52 files changed, 2353 insertions, 1045 deletions
diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c
index 638774c6f7..db9ce18887 100644
--- a/deps/uv/src/unix/async.c
+++ b/deps/uv/src/unix/async.c
@@ -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);
}
diff --git a/deps/uv/src/unix/cares.c b/deps/uv/src/unix/cares.c
index 03667fda39..a579eaa15b 100644
--- a/deps/uv/src/unix/cares.c
+++ b/deps/uv/src/unix/cares.c
@@ -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;
}
diff --git a/deps/uv/src/unix/check.c b/deps/uv/src/unix/check.c
deleted file mode 100644
index a975210072..0000000000
--- a/deps/uv/src/unix/check.c
+++ /dev/null
@@ -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);
-}
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index 9602b64294..db0cc48aba 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -19,7 +19,7 @@
*/
#include "uv.h"
-#include "unix/internal.h"
+#include "internal.h"
#include <stddef.h> /* NULL */
#include <stdio.h> /* printf */
@@ -107,14 +107,16 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
uv__fs_event_close((uv_fs_event_t*)handle);
break;
+ case UV_POLL:
+ uv__poll_close((uv_poll_t*)handle);
+ break;
+
default:
assert(0);
}
handle->flags |= UV_CLOSING;
- handle->endgame_next = handle->loop->endgame_handles;
- handle->loop->endgame_handles = handle;
- uv_unref(handle->loop);
+ uv__make_pending(handle);
}
@@ -161,24 +163,73 @@ 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__should_block(uv_loop_t* loop) {
+ return ngx_queue_empty(&loop->idle_handles)
+ && !ngx_queue_empty(&loop->active_handles);
}
-int uv_run(uv_loop_t* loop) {
- do
- uv__run(loop);
- while (uv_loop_refcount(loop) > 0);
+static int uv__run(uv_loop_t* loop) {
+ uv__run_idle(loop);
+ uv__run_pending(loop);
+
+ if (uv__has_active_handles(loop) || uv__has_active_reqs(loop)) {
+ uv__run_prepare(loop);
+ /* Need to poll even if there are no active handles left, otherwise
+ * uv_work_t reqs won't complete...
+ */
+ uv__poll(loop, uv__should_block(loop));
+ uv__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) {
+ while (uv__run(loop));
return 0;
}
@@ -195,38 +246,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:
@@ -242,11 +279,10 @@ 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));
+ case UV_FS_EVENT:
break;
- case UV_FS_EVENT:
+ case UV_POLL:
break;
default:
@@ -255,21 +291,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);
}
@@ -284,54 +310,43 @@ int64_t uv_now(uv_loop_t* loop) {
int uv_is_active(const uv_handle_t* handle) {
- switch (handle->type) {
- 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;
}
@@ -387,8 +402,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);
diff --git a/deps/uv/src/unix/dl.c b/deps/uv/src/unix/dl.c
index 88c9525f76..9eb6600112 100644
--- a/deps/uv/src/unix/dl.c
+++ b/deps/uv/src/unix/dl.c
@@ -27,65 +27,56 @@
#include <string.h>
#include <locale.h>
-/* The dl family of functions don't set errno. We need a good way to communicate
- * errors to the caller but there is only dlerror() and that returns a string -
- * a string that may or may not be safe to keep a reference to...
- */
-static const uv_err_t uv_inval_ = { UV_EINVAL, EINVAL };
-
+static int uv__dlerror(uv_lib_t* lib);
-uv_err_t uv_dlopen(const char* filename, uv_lib_t* library) {
- void* handle = dlopen(filename, RTLD_LAZY);
- if (handle == NULL) {
- return uv_inval_;
- }
- *library = handle;
- return uv_ok_;
+int uv_dlopen(const char* filename, uv_lib_t* lib) {
+ lib->errmsg = NULL;
+ lib->handle = dlopen(filename, RTLD_LAZY);
+ return uv__dlerror(lib);
}
-uv_err_t uv_dlclose(uv_lib_t library) {
- if (dlclose(library) != 0) {
- return uv_inval_;
+void uv_dlclose(uv_lib_t* lib) {
+ if (lib->errmsg) {
+ free(lib->errmsg);
+ lib->errmsg = NULL;
}
- return uv_ok_;
+ if (lib->handle) {
+ /* Ignore errors. No good way to signal them without leaking memory. */
+ dlclose(lib->handle);
+ lib->handle = NULL;
+ }
}
-uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr) {
- void* address;
-
- /* Reset error status. */
- dlerror();
+int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) {
+ dlerror(); /* Reset error status. */
+ *ptr = dlsym(lib->handle, name);
+ return uv__dlerror(lib);
+}
- address = dlsym(library, name);
- if (dlerror()) {
- return uv_inval_;
- }
-
- *ptr = (void*) address;
- return uv_ok_;
+const char* uv_dlerror(uv_lib_t* lib) {
+ return lib->errmsg ? lib->errmsg : "no error";
}
-const char *uv_dlerror(uv_lib_t library) {
- const char* buf = NULL;
- /* Make uv_dlerror() be independent of locale */
- char* loc = setlocale(LC_MESSAGES, NULL);
- if(strcmp(loc, "C") == 0) {
- return strdup(dlerror());
- } else {
- setlocale(LC_MESSAGES, "C");
- buf = dlerror();
- setlocale(LC_MESSAGES, loc);
- return strdup(buf);
- }
-}
+static int uv__dlerror(uv_lib_t* lib) {
+ char* errmsg;
+ if (lib->errmsg)
+ free(lib->errmsg);
-void uv_dlerror_free(uv_lib_t library, const char *msg) {
- free((void*)msg);
+ errmsg = dlerror();
+
+ if (errmsg) {
+ lib->errmsg = strdup(errmsg);
+ return -1;
+ }
+ else {
+ lib->errmsg = NULL;
+ return 0;
+ }
}
diff --git a/deps/uv/src/unix/ev/ev.c b/deps/uv/src/unix/ev/ev.c
index b6e190f75f..a432bfbf6b 100644
--- a/deps/uv/src/unix/ev/ev.c
+++ b/deps/uv/src/unix/ev/ev.c
@@ -2554,6 +2554,7 @@ void
ev_unref (EV_P)
{
--activecnt;
+ if (activecnt < 0) abort();
}
void
diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index 3417fa62b3..e62832db5a 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -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);
diff --git a/deps/uv/src/unix/idle.c b/deps/uv/src/unix/idle.c
deleted file mode 100644
index 5b4cf57747..0000000000
--- a/deps/uv/src/unix/idle.c
+++ /dev/null
@@ -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);
-}
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
index e8701a3f26..eca88f8e2e 100644
--- a/deps/uv/src/unix/internal.h
+++ b/deps/uv/src/unix/internal.h
@@ -86,22 +86,39 @@
enum {
UV_CLOSING = 0x01, /* uv_close() called but not finished. */
UV_CLOSED = 0x02, /* close(2) finished. */
- UV_READING = 0x04, /* uv_read_start() called. */
- UV_SHUTTING = 0x08, /* uv_shutdown() called but not complete. */
- UV_SHUT = 0x10, /* Write side closed. */
- UV_READABLE = 0x20, /* The stream is readable */
- UV_WRITABLE = 0x40, /* The stream is writable */
+ UV_STREAM_READING = 0x04, /* uv_read_start() called. */
+ UV_STREAM_SHUTTING = 0x08, /* uv_shutdown() called but not complete. */
+ UV_STREAM_SHUT = 0x10, /* Write side closed. */
+ UV_STREAM_READABLE = 0x20, /* The stream is readable */
+ 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);
@@ -141,12 +162,11 @@ int uv__tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay);
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
void uv__pipe_accept(EV_P_ ev_io* watcher, int revents);
-/* 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);
+/* poll */
+void uv__poll_close(uv_poll_t* handle);
+int uv__poll_active(const uv_poll_t* handle);
+/* various */
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);
@@ -159,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);
diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c
index 404632329c..ee1bbd174c 100644
--- a/deps/uv/src/unix/kqueue.c
+++ b/deps/uv/src/unix/kqueue.c
@@ -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;
diff --git a/deps/uv/src/unix/linux/inotify.c b/deps/uv/src/unix/linux/inotify.c
index 24ddbcbcee..564e47a547 100644
--- a/deps/uv/src/unix/linux/inotify.c
+++ b/deps/uv/src/unix/linux/inotify.c
@@ -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);
}
diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c
index 5580aba3fe..aca2a889fb 100644
--- a/deps/uv/src/unix/loop.c
+++ b/deps/uv/src/unix/loop.c
@@ -33,15 +33,31 @@ 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;
#endif
+#if HAVE_PORTS_FS
+ loop->fs_fd = -1;
+#endif
return 0;
}
@@ -55,4 +71,45 @@ void uv__loop_delete(uv_loop_t* loop) {
close(loop->inotify_fd);
loop->inotify_fd = -1;
#endif
+#if HAVE_PORTS_FS
+ if (loop->fs_fd != -1)
+ 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
diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c
index 7d0b2ec70b..91afb0811e 100644
--- a/deps/uv/src/unix/pipe.c
+++ b/deps/uv/src/unix/pipe.c
@@ -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;
@@ -163,7 +165,9 @@ void uv__pipe_close(uv_pipe_t* handle) {
void uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
- uv__stream_open((uv_stream_t*)handle, fd, UV_READABLE | UV_WRITABLE);
+ uv__stream_open((uv_stream_t*)handle,
+ fd,
+ UV_STREAM_READABLE | UV_STREAM_WRITABLE);
}
@@ -204,24 +208,24 @@ void uv_pipe_connect(uv_connect_t* req,
goto out;
}
- uv__stream_open((uv_stream_t*)handle, sockfd, UV_READABLE | UV_WRITABLE);
-
+ 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.
diff --git a/deps/uv/src/unix/poll.c b/deps/uv/src/unix/poll.c
new file mode 100644
index 0000000000..45def2c15a
--- /dev/null
+++ b/deps/uv/src/unix/poll.c
@@ -0,0 +1,123 @@
+/* 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"
+
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+
+
+static void uv__poll_io(EV_P_ ev_io* watcher, int ev_events) {
+ uv_poll_t* handle = watcher->data;
+ int events;
+
+ if (ev_events & EV_ERROR) {
+ /* An error happened. Libev has implicitly stopped the watcher, but we */
+ /* need to fix the refcount. */
+ uv__handle_stop(handle);
+ uv__set_sys_error(handle->loop, EBADF);
+ handle->poll_cb(handle, -1, 0);
+ return;
+ }
+
+ assert(ev_events & (EV_READ | EV_WRITE));
+ assert((ev_events & ~(EV_READ | EV_WRITE)) == 0);
+
+ events = 0;
+ if (ev_events & EV_READ)
+ events |= UV_READABLE;
+ if (ev_events & EV_WRITE)
+ events |= UV_WRITABLE;
+
+ handle->poll_cb(handle, 0, events);
+}
+
+
+int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
+ uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL);
+ loop->counters.poll_init++;
+
+ handle->fd = fd;
+ handle->poll_cb = NULL;
+
+ ev_init(&handle->io_watcher, uv__poll_io);
+ handle->io_watcher.data = handle;
+
+ return 0;
+}
+
+
+int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
+ uv_os_sock_t socket) {
+ return uv_poll_init(loop, handle, socket);
+}
+
+
+static void uv__poll_stop(uv_poll_t* handle) {
+ ev_io_stop(handle->loop->ev, &handle->io_watcher);
+ uv__handle_stop(handle);
+}
+
+
+int uv_poll_stop(uv_poll_t* handle) {
+ assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
+ uv__poll_stop(handle);
+ return 0;
+}
+
+
+int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb poll_cb) {
+ int ev_events;
+
+ assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0);
+ assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
+
+ if (events == 0) {
+ uv__poll_stop(handle);
+ return 0;
+ }
+
+ ev_events = 0;
+ if (events & UV_READABLE)
+ ev_events |= EV_READ;
+ if (events & UV_WRITABLE)
+ ev_events |= EV_WRITE;
+
+ ev_io_set(&handle->io_watcher, handle->fd, ev_events);
+ ev_io_start(handle->loop->ev, &handle->io_watcher);
+
+ handle->poll_cb = poll_cb;
+ uv__handle_start(handle);
+
+ return 0;
+}
+
+
+void uv__poll_close(uv_poll_t* handle) {
+ uv__poll_stop(handle);
+}
+
+
+int uv__poll_active(const uv_poll_t* handle) {
+ return ev_is_active(&handle->io_watcher);
+}
diff --git a/deps/uv/src/unix/prepare.c b/deps/uv/src/unix/prepare.c
deleted file mode 100644
index 6c18fbd7fc..0000000000
--- a/deps/uv/src/unix/prepare.c
+++ /dev/null
@@ -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);
-}
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
index 10872cce61..bccaf17147 100644
--- a/deps/uv/src/unix/process.c
+++ b/deps/uv/src/unix/process.c
@@ -25,7 +25,6 @@
#include <assert.h>
#include <errno.h>
#include <sys/wait.h>
-#include <fcntl.h> /* O_CLOEXEC, O_NONBLOCK */
#include <poll.h>
#include <unistd.h>
#include <stdio.h>
@@ -108,10 +107,10 @@ int uv__make_pipe(int fds[2], int flags) {
#if __linux__
int fl;
- fl = O_CLOEXEC;
+ fl = UV__O_CLOEXEC;
if (flags & UV__F_NONBLOCK)
- fl |= O_NONBLOCK;
+ fl |= UV__O_NONBLOCK;
if (uv__pipe2(fds, fl) == 0)
return 0;
@@ -182,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;
@@ -318,7 +318,8 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
assert(stdin_pipe[0] >= 0);
close(stdin_pipe[0]);
uv__nonblock(stdin_pipe[1], 1);
- flags = UV_WRITABLE | (options.stdin_stream->ipc ? UV_READABLE : 0);
+ flags = UV_STREAM_WRITABLE |
+ (options.stdin_stream->ipc ? UV_STREAM_READABLE : 0);
uv__stream_open((uv_stream_t*)options.stdin_stream, stdin_pipe[1],
flags);
}
@@ -328,7 +329,8 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
assert(stdout_pipe[1] >= 0);
close(stdout_pipe[1]);
uv__nonblock(stdout_pipe[0], 1);
- flags = UV_READABLE | (options.stdout_stream->ipc ? UV_WRITABLE : 0);
+ flags = UV_STREAM_READABLE |
+ (options.stdout_stream->ipc ? UV_STREAM_WRITABLE : 0);
uv__stream_open((uv_stream_t*)options.stdout_stream, stdout_pipe[0],
flags);
}
@@ -338,7 +340,8 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
assert(stderr_pipe[1] >= 0);
close(stderr_pipe[1]);
uv__nonblock(stderr_pipe[0], 1);
- flags = UV_READABLE | (options.stderr_stream->ipc ? UV_WRITABLE : 0);
+ flags = UV_STREAM_READABLE |
+ (options.stderr_stream->ipc ? UV_STREAM_WRITABLE : 0);
uv__stream_open((uv_stream_t*)options.stderr_stream, stderr_pipe[0],
flags);
}
@@ -382,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);
}
diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index b71f9bdde6..76e2581908 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -62,6 +62,7 @@ void uv__stream_init(uv_loop_t* loop,
stream->close_cb = NULL;
stream->connection_cb = NULL;
stream->connect_req = NULL;
+ stream->shutdown_req = NULL;
stream->accepted_fd = -1;
stream->fd = -1;
stream->delayed_error = 0;
@@ -128,11 +129,20 @@ void uv__stream_destroy(uv_stream_t* stream) {
assert(stream->flags & UV_CLOSED);
+ if (stream->connect_req) {
+ uv__req_unregister(stream->loop, stream->connect_req);
+ uv__set_artificial_error(stream->loop, UV_EINTR);
+ stream->connect_req->cb(stream->connect_req, -1);
+ stream->connect_req = NULL;
+ }
+
while (!ngx_queue_empty(&stream->write_queue)) {
q = ngx_queue_head(&stream->write_queue);
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 +157,19 @@ 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_SHUTTING) {
- uv_shutdown_t* req = stream->shutdown_req;
- if (req && req->cb) {
- uv__set_artificial_error(stream->loop, UV_EINTR);
- req->cb(req, -1);
- }
+ if (stream->shutdown_req) {
+ uv__req_unregister(stream->loop, stream->shutdown_req);
+ uv__set_artificial_error(stream->loop, UV_EINTR);
+ stream->shutdown_req->cb(stream->shutdown_req, -1);
+ stream->shutdown_req = NULL;
}
}
@@ -234,7 +245,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
}
if (uv__stream_open(streamClient, streamServer->accepted_fd,
- UV_READABLE | UV_WRITABLE)) {
+ UV_STREAM_READABLE | UV_STREAM_WRITABLE)) {
/* TODO handle error */
close(streamServer->accepted_fd);
streamServer->accepted_fd = -1;
@@ -252,15 +263,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;
}
@@ -293,13 +315,14 @@ static void uv__drain(uv_stream_t* stream) {
ev_io_stop(stream->loop->ev, &stream->write_watcher);
/* Shutdown? */
- if ((stream->flags & UV_SHUTTING) &&
+ if ((stream->flags & UV_STREAM_SHUTTING) &&
!(stream->flags & UV_CLOSING) &&
- !(stream->flags & UV_SHUT)) {
+ !(stream->flags & UV_STREAM_SHUT)) {
assert(stream->shutdown_req);
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(). */
@@ -309,7 +332,7 @@ static void uv__drain(uv_stream_t* stream) {
}
} else {
uv__set_sys_error(stream->loop, 0);
- ((uv_handle_t*) stream)->flags |= UV_SHUT;
+ ((uv_handle_t*) stream)->flags |= UV_STREAM_SHUT;
if (req->cb) {
req->cb(req, 0);
}
@@ -499,24 +522,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));
@@ -558,11 +578,11 @@ static void uv__read(uv_stream_t* stream) {
char cmsg_space[64];
struct ev_loop* ev = stream->loop->ev;
- /* XXX: Maybe instead of having UV_READING we just test if
+ /* XXX: Maybe instead of having UV_STREAM_READING we just test if
* tcp->read_cb is NULL or not?
*/
while ((stream->read_cb || stream->read2_cb) &&
- stream->flags & UV_READING) {
+ stream->flags & UV_STREAM_READING) {
assert(stream->alloc_cb);
buf = stream->alloc_cb((uv_handle_t*)stream, 64 * 1024);
@@ -598,7 +618,7 @@ static void uv__read(uv_stream_t* stream) {
/* Error */
if (errno == EAGAIN || errno == EWOULDBLOCK) {
/* Wait for the next one. */
- if (stream->flags & UV_READING) {
+ if (stream->flags & UV_STREAM_READING) {
ev_io_start(ev, &stream->read_watcher);
}
uv__set_sys_error(stream->loop, EAGAIN);
@@ -628,6 +648,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);
@@ -691,8 +713,8 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
"uv_shutdown (unix) only supports uv_handle_t right now");
assert(stream->fd >= 0);
- if (!(stream->flags & UV_WRITABLE) ||
- stream->flags & UV_SHUT ||
+ if (!(stream->flags & UV_STREAM_WRITABLE) ||
+ stream->flags & UV_STREAM_SHUT ||
stream->flags & UV_CLOSED ||
stream->flags & UV_CLOSING) {
uv__set_sys_error(stream->loop, EINVAL);
@@ -704,9 +726,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_SHUTTING;
-
+ stream->flags |= UV_STREAM_SHUTTING;
ev_io_start(stream->loop->ev, &stream->write_watcher);
@@ -714,6 +734,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,32 +792,24 @@ 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);
- }
+ stream->connect_req = NULL;
+ 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);
}
}
int uv__connect(uv_connect_t* req, uv_stream_t* stream, struct sockaddr* addr,
- socklen_t addrlen, uv_connect_cb cb) {
+ socklen_t addrlen, uv_connect_cb cb) {
int sockfd;
int r;
@@ -802,7 +819,9 @@ int uv__connect(uv_connect_t* req, uv_stream_t* stream, struct sockaddr* addr,
return -1;
}
- if (uv__stream_open(stream, sockfd, UV_READABLE | UV_WRITABLE)) {
+ if (uv__stream_open(stream,
+ sockfd,
+ UV_STREAM_READABLE | UV_STREAM_WRITABLE)) {
close(sockfd);
return -2;
}
@@ -853,9 +872,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;
}
@@ -956,10 +974,10 @@ int uv__read_start_common(uv_stream_t* stream, uv_alloc_cb alloc_cb,
return -1;
}
- /* The UV_READING flag is irrelevant of the state of the tcp - it just
+ /* 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_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
@@ -976,6 +994,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;
}
@@ -994,7 +1014,8 @@ 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);
- stream->flags &= ~UV_READING;
+ uv__handle_stop(stream);
+ stream->flags &= ~UV_STREAM_READING;
stream->read_cb = NULL;
stream->read2_cb = NULL;
stream->alloc_cb = NULL;
@@ -1003,12 +1024,12 @@ int uv_read_stop(uv_stream_t* stream) {
int uv_is_readable(const uv_stream_t* stream) {
- return stream->flags & UV_READABLE;
+ return stream->flags & UV_STREAM_READABLE;
}
int uv_is_writable(const uv_stream_t* stream) {
- return stream->flags & UV_WRITABLE;
+ return stream->flags & UV_STREAM_WRITABLE;
}
diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c
index 0057e68651..f341297bba 100644
--- a/deps/uv/src/unix/sunos.c
+++ b/deps/uv/src/unix/sunos.c
@@ -42,6 +42,11 @@
#if HAVE_PORTS_FS
# include <sys/port.h>
# include <port.h>
+
+# define PORT_FIRED 0x69
+# define PORT_UNUSED 0x0
+# define PORT_LOADED 0x99
+# define PORT_DELETED -1
#endif
#if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64)
@@ -109,36 +114,41 @@ void uv_loadavg(double avg[3]) {
#if HAVE_PORTS_FS
static void uv__fs_event_rearm(uv_fs_event_t *handle) {
- if (port_associate(handle->fd,
+ if (handle->fd == -1)
+ return;
+
+ if (port_associate(handle->loop->fs_fd,
PORT_SOURCE_FILE,
(uintptr_t) &handle->fo,
FILE_ATTRIB | FILE_MODIFIED,
- NULL) == -1) {
+ handle) == -1) {
uv__set_sys_error(handle->loop, errno);
}
+ handle->fd = PORT_LOADED;
}
static void uv__fs_event_read(EV_P_ ev_io* w, int revents) {
uv_fs_event_t *handle;
+ uv_loop_t *loop_;
timespec_t timeout;
port_event_t pe;
int events;
int r;
- handle = container_of(w, uv_fs_event_t, event_watcher);
+ loop_ = container_of(w, uv_loop_t, fs_event_watcher);
do {
/* TODO use port_getn() */
do {
memset(&timeout, 0, sizeof timeout);
- r = port_get(handle->fd, &pe, &timeout);
+ r = port_get(loop_->fs_fd, &pe, &timeout);
}
while (r == -1 && errno == EINTR);
if (r == -1 && errno == ETIME)
break;
-
+ handle = (uv_fs_event_t *)pe.portev_user;
assert((r == 0) && "unexpected port_get() error");
events = 0;
@@ -147,12 +157,12 @@ static void uv__fs_event_read(EV_P_ ev_io* w, int revents) {
if (pe.portev_events & ~(FILE_ATTRIB | FILE_MODIFIED))
events |= UV_RENAME;
assert(events != 0);
-
+ handle->fd = PORT_FIRED;
handle->cb(handle, NULL, events, 0);
}
- while (handle->fd != -1);
+ while (handle->fd != PORT_DELETED);
- if (handle->fd != -1)
+ if (handle->fd != PORT_DELETED)
uv__fs_event_rearm(handle);
}
@@ -163,39 +173,45 @@ int uv_fs_event_init(uv_loop_t* loop,
uv_fs_event_cb cb,
int flags) {
int portfd;
+ int first_run = 0;
loop->counters.fs_event_init++;
/* We don't support any flags yet. */
assert(!flags);
-
+ if (loop->fs_fd == -1) {
if ((portfd = port_create()) == -1) {
uv__set_sys_error(loop, errno);
return -1;
}
+ loop->fs_fd = portfd;
+ first_run = 1;
+ }
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 = portfd;
+ handle->fd = PORT_UNUSED;
handle->cb = cb;
memset(&handle->fo, 0, sizeof handle->fo);
handle->fo.fo_name = handle->filename;
uv__fs_event_rearm(handle);
- ev_io_init(&handle->event_watcher, uv__fs_event_read, portfd, EV_READ);
- ev_io_start(loop->ev, &handle->event_watcher);
- ev_unref(loop->ev);
+ 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);
+ }
return 0;
}
void uv__fs_event_close(uv_fs_event_t* handle) {
- ev_ref(handle->loop->ev);
- ev_io_stop(handle->loop->ev, &handle->event_watcher);
- close(handle->fd);
- handle->fd = -1;
+ if (handle->fd == PORT_FIRED) {
+ port_dissociate(handle->loop->fs_fd, PORT_SOURCE_FILE, (uintptr_t)&handle->fo);
+ }
+ handle->fd = PORT_DELETED;
free(handle->filename);
handle->filename = NULL;
handle->fo.fo_name = NULL;
diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c
index be038478f8..a28db550ef 100644
--- a/deps/uv/src/unix/tcp.c
+++ b/deps/uv/src/unix/tcp.c
@@ -50,7 +50,9 @@ static int uv__bind(uv_tcp_t* tcp,
goto out;
}
- if (uv__stream_open((uv_stream_t*)tcp, tcp->fd, UV_READABLE | UV_WRITABLE)) {
+ if (uv__stream_open((uv_stream_t*)tcp,
+ tcp->fd,
+ UV_STREAM_READABLE | UV_STREAM_WRITABLE)) {
close(tcp->fd);
tcp->fd = -1;
status = -2;
@@ -181,7 +183,7 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
return -1;
}
- if (uv__stream_open((uv_stream_t*)tcp, tcp->fd, UV_READABLE)) {
+ if (uv__stream_open((uv_stream_t*)tcp, tcp->fd, UV_STREAM_READABLE)) {
close(tcp->fd);
tcp->fd = -1;
return -1;
diff --git a/deps/uv/src/unix/timer.c b/deps/uv/src/unix/timer.c
index 6a002294c9..8463088ac9 100644
--- a/deps/uv/src/unix/timer.c
+++ b/deps/uv/src/unix/timer.c
@@ -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);
}
diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c
index c1429660eb..572d19c60a 100644
--- a/deps/uv/src/unix/tty.c
+++ b/deps/uv/src/unix/tty.c
@@ -38,10 +38,10 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
if (readable) {
uv__nonblock(fd, 1);
- uv__stream_open((uv_stream_t*)tty, fd, UV_READABLE);
+ uv__stream_open((uv_stream_t*)tty, fd, UV_STREAM_READABLE);
} else {
/* Note: writable tty we set to blocking mode. */
- uv__stream_open((uv_stream_t*)tty, fd, UV_WRITABLE);
+ uv__stream_open((uv_stream_t*)tty, fd, UV_STREAM_WRITABLE);
tty->blocking = 1;
}
diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c
index 105bdc048a..c67dcc2c9d 100644
--- a/deps/uv/src/unix/udp.c
+++ b/deps/uv/src/unix/udp.c
@@ -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);
diff --git a/deps/uv/src/unix/uv-eio.c b/deps/uv/src/unix/uv-eio.c
index 517d119142..b36eea3099 100644
--- a/deps/uv/src/unix/uv-eio.c
+++ b/deps/uv/src/unix/uv-eio.c
@@ -27,47 +27,31 @@
#include <stdio.h>
-static void uv_eio_do_poll(uv_idle_t* watcher, int status) {
- assert(watcher == &(watcher->loop->uv_eio_poller));
+static uv_once_t uv__eio_init_once_guard = UV_ONCE_INIT;
- /* 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"); */
+static void uv_eio_do_poll(uv_idle_t* watcher, int status) {
+ 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);
- }
}
@@ -77,13 +61,8 @@ static void uv_eio_done_poll_notifier_cb(uv_async_t* watcher, int revents) {
*/
static void uv_eio_want_poll(eio_channel *channel) {
/* Signal the main thread that eio_poll need to be processed. */
-
- /*
- * TODO need to select the correct uv_loop_t and async_send to
- * uv_eio_want_poll_notifier.
- */
-
- uv_async_send(&((uv_loop_t *)channel->data)->uv_eio_want_poll_notifier);
+ uv_loop_t* loop = channel->data;
+ uv_async_send(&loop->uv_eio_want_poll_notifier);
}
@@ -92,7 +71,8 @@ static void uv_eio_done_poll(eio_channel *channel) {
* Signal the main thread that we should stop calling eio_poll().
* from the idle watcher.
*/
- uv_async_send(&((uv_loop_t *)channel->data)->uv_eio_done_poll_notifier);
+ uv_loop_t* loop = channel->data;
+ uv_async_send(&loop->uv_eio_done_poll_notifier);
}
@@ -100,25 +80,20 @@ 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);
+ uv_idle_init(loop, &loop->uv_eio_poller);
+ uv_idle_start(&loop->uv_eio_poller, uv_eio_do_poll);
- 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);
+ loop->uv_eio_want_poll_notifier.data = loop;
+ uv_async_init(loop, &loop->uv_eio_want_poll_notifier,
+ uv_eio_want_poll_notifier_cb);
- uv_async_init(loop, &loop->uv_eio_done_poll_notifier,
- uv_eio_done_poll_notifier_cb);
- uv_unref(loop);
+ uv_async_init(loop, &loop->uv_eio_done_poll_notifier,
+ uv_eio_done_poll_notifier_cb);
- uv_once(&uv__eio_init_once_guard, uv__eio_init);
- }
+ uv_once(&uv__eio_init_once_guard, uv__eio_init);
}
diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c
index c8192bd7db..08aaebf3f0 100644
--- a/deps/uv/src/uv-common.c
+++ b/deps/uv/src/uv-common.c
@@ -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);
+}
diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h
index e82f584272..efc07601a9 100644
--- a/deps/uv/src/uv-common.h
+++ b/deps/uv/src/uv-common.h
@@ -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_ */
diff --git a/deps/uv/src/win/async.c b/deps/uv/src/win/async.c
index b68a868054..9df75e08e9 100644
--- a/deps/uv/src/win/async.c
+++ b/deps/uv/src/win/async.c
@@ -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;
diff --git a/deps/uv/src/win/cares.c b/deps/uv/src/win/cares.c
index 1592d12345..359bc213ed 100644
--- a/deps/uv/src/win/cares.c
+++ b/deps/uv/src/win/cares.c
@@ -22,7 +22,6 @@
#include <assert.h>
#include "uv.h"
-#include "../uv-common.h"
#include "internal.h"
@@ -108,8 +107,6 @@ static void uv_ares_sockstate_cb(void *data, ares_socket_t sock, int read,
uv_loop_t* loop = (uv_loop_t*) data;
uv_ares_task_t* uv_handle_ares = uv_find_ares_handle(loop, sock);
- int timeoutms = 0;
-
if (read == 0 && write == 0) {
/* if read and write are 0, cleanup existing data */
/* The code assumes that c-ares does a callback with read = 0 and */
@@ -134,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;
@@ -180,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.
@@ -231,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);
diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c
index 1358cb29cb..27f3438b92 100644
--- a/deps/uv/src/win/core.c
+++ b/deps/uv/src/win/core.c
@@ -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;
@@ -84,6 +89,8 @@ static void uv_loop_init(uv_loop_t* loop) {
loop->next_check_handle = NULL;
loop->next_idle_handle = NULL;
+ memset(&loop->poll_peer_sockets, 0, sizeof loop->poll_peer_sockets);
+
loop->ares_active_sockets = 0;
loop->ares_chan = NULL;
@@ -130,26 +137,19 @@ uv_loop_t* uv_loop_new(void) {
void uv_loop_delete(uv_loop_t* loop) {
if (loop != &uv_default_loop_) {
+ int i;
+ for (i = 0; i < ARRAY_SIZE(loop->poll_peer_sockets); i++) {
+ SOCKET sock = loop->poll_peer_sockets[i];
+ if (sock != 0 && sock != INVALID_SOCKET) {
+ closesocket(sock);
+ }
+ }
+
free(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;
@@ -216,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)); \
@@ -230,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; \
} \
\
@@ -239,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) \
}
@@ -267,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;
}
diff --git a/deps/uv/src/win/dl.c b/deps/uv/src/win/dl.c
index 08374d37fb..88ddd74b54 100644
--- a/deps/uv/src/win/dl.c
+++ b/deps/uv/src/win/dl.c
@@ -22,61 +22,65 @@
#include "uv.h"
#include "internal.h"
-__declspec( thread ) DWORD saved_errno = 0;
+static int uv__dlerror(uv_lib_t* lib, int errorno);
-uv_err_t uv_dlopen(const char* filename, uv_lib_t* library) {
+
+int uv_dlopen(const char* filename, uv_lib_t* lib) {
wchar_t filename_w[32768];
- HMODULE handle;
- if (!uv_utf8_to_utf16(filename,
- filename_w,
- sizeof(filename_w) / sizeof(wchar_t))) {
- saved_errno = GetLastError();
- return uv__new_sys_error(saved_errno);
+ lib->handle = NULL;
+ lib->errmsg = NULL;
+
+ if (!uv_utf8_to_utf16(filename, filename_w, ARRAY_SIZE(filename_w))) {
+ return uv__dlerror(lib, GetLastError());
}
- handle = LoadLibraryExW(filename_w, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
- if (handle == NULL) {
- saved_errno = GetLastError();
- return uv__new_sys_error(saved_errno);
+ lib->handle = LoadLibraryExW(filename_w, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+ if (lib->handle == NULL) {
+ return uv__dlerror(lib, GetLastError());
}
- *library = handle;
- return uv_ok_;
+ return 0;
}
-uv_err_t uv_dlclose(uv_lib_t library) {
- if (!FreeLibrary(library)) {
- saved_errno = GetLastError();
- return uv__new_sys_error(saved_errno);
+void uv_dlclose(uv_lib_t* lib) {
+ if (lib->errmsg) {
+ LocalFree((void*)lib->errmsg);
+ lib->errmsg = NULL;
}
- return uv_ok_;
+ if (lib->handle) {
+ /* Ignore errors. No good way to signal them without leaking memory. */
+ FreeLibrary(lib->handle);
+ lib->handle = NULL;
+ }
}
-uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr) {
- FARPROC proc = GetProcAddress(library, name);
- if (proc == NULL) {
- saved_errno = GetLastError();
- return uv__new_sys_error(saved_errno);
- }
-
- *ptr = (void*) proc;
- return uv_ok_;
+int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) {
+ *ptr = (void*) GetProcAddress(lib->handle, name);
+ return uv__dlerror(lib, *ptr ? 0 : GetLastError());
}
-const char *uv_dlerror(uv_lib_t library) {
- char* buf = NULL;
- FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS, NULL, saved_errno,
- MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (LPSTR)&buf, 0, NULL);
- return buf;
+const char* uv_dlerror(uv_lib_t* lib) {
+ return lib->errmsg ? lib->errmsg : "no error";
}
-void uv_dlerror_free(uv_lib_t library, const char *msg) {
- LocalFree((LPVOID)msg);
+static int uv__dlerror(uv_lib_t* lib, int errorno) {
+ if (lib->errmsg) {
+ LocalFree((void*)lib->errmsg);
+ lib->errmsg = NULL;
+ }
+
+ if (errorno) {
+ FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
+ MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+ (LPSTR)&lib->errmsg, 0, NULL);
+ }
+
+ return errorno ? -1 : 0;
}
diff --git a/deps/uv/src/win/error.c b/deps/uv/src/win/error.c
index 294041264c..bdbb3b293e 100644
--- a/deps/uv/src/win/error.c
+++ b/deps/uv/src/win/error.c
@@ -26,7 +26,6 @@
#include <string.h>
#include "uv.h"
-#include "../uv-common.h"
#include "internal.h"
diff --git a/deps/uv/src/win/fs-event.c b/deps/uv/src/win/fs-event.c
index 1003201f3f..61f9de23ab 100644
--- a/deps/uv/src/win/fs-event.c
+++ b/deps/uv/src/win/fs-event.c
@@ -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++;
}
@@ -109,7 +108,7 @@ static int uv_split_path(const wchar_t* filename, wchar_t** dir,
return -1;
}
}
-
+
*file = wcsdup(filename);
} else {
if (dir) {
@@ -152,7 +151,7 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}
- if (!uv_utf8_to_utf16(filename, filenamew,
+ if (!uv_utf8_to_utf16(filename, filenamew,
name_size / sizeof(wchar_t))) {
uv__set_sys_error(loop, GetLastError());
return -1;
@@ -172,11 +171,11 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
handle->dirw = filenamew;
dir_to_watch = filenamew;
} else {
- /*
+ /*
* filename is a file. So we split filename into dir & file parts, and
* watch the dir directory.
*/
-
+
/* Convert to short path. */
if (!GetShortPathNameW(filenamew, short_path, ARRAY_SIZE(short_path))) {
last_error = GetLastError();
@@ -226,7 +225,7 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
goto error;
}
- handle->buffer = (char*)_aligned_malloc(uv_directory_watcher_buffer_size,
+ handle->buffer = (char*)_aligned_malloc(uv_directory_watcher_buffer_size,
sizeof(DWORD));
if (!handle->buffer) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
@@ -317,7 +316,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
assert(!filename);
assert(!long_filenamew);
- /*
+ /*
* Fire the event only if we were asked to watch a directory,
* or if the filename filter matches.
*/
@@ -328,8 +327,8 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
file_info->FileNameLength / sizeof(wchar_t)) == 0) {
if (handle->dirw) {
- /*
- * We attempt to convert the file name to its long form for
+ /*
+ * We attempt to convert the file name to its long form for
* events that still point to valid files on disk.
* For removed and renamed events, we do not provide the file name.
*/
@@ -382,7 +381,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
}
}
- /*
+ /*
* If we couldn't get the long name - just use the name
* provided by ReadDirectoryChangesW.
*/
@@ -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);
}
}
diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c
index 3cbb66f242..924554b3e7 100644
--- a/deps/uv/src/win/fs.c
+++ b/deps/uv/src/win/fs.c
@@ -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_);
@@ -89,6 +89,16 @@
return; \
}
+#define IS_SLASH(c) ((c) == L'\\' || (c) == L'/')
+#define IS_LETTER(c) (((c) >= L'a' && (c) <= L'z') || \
+ ((c) >= L'A' && (c) <= L'Z'))
+
+const wchar_t JUNCTION_PREFIX[] = L"\\??\\";
+const wchar_t JUNCTION_PREFIX_LEN = 4;
+
+const wchar_t LONG_PATH_PREFIX[] = L"\\\\?\\";
+const wchar_t LONG_PATH_PREFIX_LEN = 4;
+
void uv_fs_init() {
_fmode = _O_BINARY;
@@ -128,6 +138,61 @@ static void uv_fs_req_init_sync(uv_loop_t* loop, uv_fs_t* req,
}
+static int is_path_dir(const wchar_t* path) {
+ DWORD attr = GetFileAttributesW(path);
+
+ if (attr != INVALID_FILE_ATTRIBUTES) {
+ return attr & FILE_ATTRIBUTE_DIRECTORY ? 1 : 0;
+ } else {
+ return 0;
+ }
+}
+
+
+static int get_reparse_point(HANDLE handle, int* target_length) {
+ void* buffer = NULL;
+ REPARSE_DATA_BUFFER* reparse_data;
+ DWORD bytes_returned;
+ int rv = 0;
+
+ buffer = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
+ if (!buffer) {
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ }
+
+ if (!DeviceIoControl(handle,
+ FSCTL_GET_REPARSE_POINT,
+ NULL,
+ 0,
+ buffer,
+ MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
+ &bytes_returned,
+ NULL)) {
+ free(buffer);
+ return 0;
+ }
+
+ reparse_data = (REPARSE_DATA_BUFFER*)buffer;
+
+ if (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
+ rv = 1;
+ if (target_length) {
+ *target_length = reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /
+ sizeof(wchar_t);
+ }
+ } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
+ rv = 1;
+ if (target_length) {
+ *target_length = reparse_data->MountPointReparseBuffer.SubstituteNameLength /
+ sizeof(wchar_t);
+ }
+ }
+
+ free(buffer);
+ return rv;
+}
+
+
void fs__open(uv_fs_t* req, const wchar_t* path, int flags, int mode) {
DWORD access;
DWORD share;
@@ -224,10 +289,8 @@ void fs__open(uv_fs_t* req, const wchar_t* path, int flags, int mode) {
goto end;
}
- /* Figure out whether path is a file or a directory. */
- if (GetFileAttributesW(path) & FILE_ATTRIBUTE_DIRECTORY) {
- attributes |= FILE_FLAG_BACKUP_SEMANTICS;
- }
+ /* Setting this flag makes it possible to open a directory. */
+ attributes |= FILE_FLAG_BACKUP_SEMANTICS;
file = CreateFileW(path,
access,
@@ -349,20 +412,53 @@ void fs__write(uv_fs_t* req, uv_file file, void *buf, size_t length,
}
-void fs__unlink(uv_fs_t* req, const wchar_t* path) {
- int result = _wunlink(path);
+void fs__rmdir(uv_fs_t* req, const wchar_t* path) {
+ int result = _wrmdir(path);
SET_REQ_RESULT(req, result);
}
-void fs__mkdir(uv_fs_t* req, const wchar_t* path, int mode) {
- int result = _wmkdir(path);
- SET_REQ_RESULT(req, result);
+void fs__unlink(uv_fs_t* req, const wchar_t* path) {
+ int result;
+ HANDLE handle;
+ BY_HANDLE_FILE_INFORMATION info;
+ int is_dir_symlink;
+
+ handle = CreateFileW(path,
+ 0,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ return;
+ }
+
+ if (!GetFileInformationByHandle(handle, &info)) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ CloseHandle(handle);
+ return;
+ }
+
+ is_dir_symlink = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
+ get_reparse_point(handle, NULL);
+
+ CloseHandle(handle);
+
+ if (is_dir_symlink) {
+ fs__rmdir(req, path);
+ } else {
+ result = _wunlink(path);
+ SET_REQ_RESULT(req, result);
+ }
}
-void fs__rmdir(uv_fs_t* req, const wchar_t* path) {
- int result = _wrmdir(path);
+void fs__mkdir(uv_fs_t* req, const wchar_t* path, int mode) {
+ int result = _wmkdir(path);
SET_REQ_RESULT(req, result);
}
@@ -474,18 +570,26 @@ void fs__readdir(uv_fs_t* req, const wchar_t* path, int flags) {
}
-static void fs__stat(uv_fs_t* req, const wchar_t* path) {
+static void fs__stat(uv_fs_t* req, const wchar_t* path, int link) {
HANDLE handle;
+ int target_length;
+ int symlink = 0;
BY_HANDLE_FILE_INFORMATION info;
+ DWORD flags;
req->ptr = NULL;
+ flags = FILE_FLAG_BACKUP_SEMANTICS;
+
+ if (link) {
+ flags |= FILE_FLAG_OPEN_REPARSE_POINT;
+ }
handle = CreateFileW(path,
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS,
+ flags,
NULL);
if (handle == INVALID_HANDLE_VALUE) {
SET_REQ_WIN32_ERROR(req, GetLastError());
@@ -502,32 +606,37 @@ static void fs__stat(uv_fs_t* req, const wchar_t* path) {
/* TODO: set st_dev and st_ino? */
- if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
- req->stat.st_mode |= (_S_IREAD + (_S_IREAD >> 3) + (_S_IREAD >> 6));
+ if (link && get_reparse_point(handle, &target_length)) {
+ req->stat.st_mode = S_IFLNK;
+ /* Adjust for long path */
+ req->stat.st_size = target_length - JUNCTION_PREFIX_LEN;
} else {
- req->stat.st_mode |= ((_S_IREAD|_S_IWRITE) + ((_S_IREAD|_S_IWRITE) >> 3) +
- ((_S_IREAD|_S_IWRITE) >> 6));
- }
+ if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
+ req->stat.st_mode |= (_S_IREAD + (_S_IREAD >> 3) + (_S_IREAD >> 6));
+ } else {
+ req->stat.st_mode |= ((_S_IREAD|_S_IWRITE) + ((_S_IREAD|_S_IWRITE) >> 3) +
+ ((_S_IREAD|_S_IWRITE) >> 6));
+ }
- if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- req->stat.st_mode |= _S_IFDIR;
- } else {
- req->stat.st_mode |= _S_IFREG;
+ if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ req->stat.st_mode |= _S_IFDIR;
+ } else {
+ req->stat.st_mode |= _S_IFREG;
+ }
+
+ req->stat.st_size = ((int64_t) info.nFileSizeHigh << 32) +
+ (int64_t) info.nFileSizeLow;
}
uv_filetime_to_time_t(&info.ftLastWriteTime, &(req->stat.st_mtime));
uv_filetime_to_time_t(&info.ftLastAccessTime, &(req->stat.st_atime));
uv_filetime_to_time_t(&info.ftCreationTime, &(req->stat.st_ctime));
- req->stat.st_size = ((int64_t) info.nFileSizeHigh << 32) +
- (int64_t) info.nFileSizeLow;
-
req->stat.st_nlink = (info.nNumberOfLinks <= SHRT_MAX) ?
(short) info.nNumberOfLinks : SHRT_MAX;
req->ptr = &req->stat;
req->result = 0;
-
CloseHandle(handle);
}
@@ -573,12 +682,28 @@ void fs__fsync(uv_fs_t* req, uv_file file) {
void fs__ftruncate(uv_fs_t* req, uv_file file, int64_t offset) {
- int result;
+ HANDLE handle;
+ NTSTATUS status;
+ IO_STATUS_BLOCK io_status;
+ FILE_END_OF_FILE_INFORMATION eof_info;
VERIFY_UV_FILE(file, req);
- result = _chsize_s(file, offset);
- SET_REQ_RESULT(req, result);
+ handle = (HANDLE)_get_osfhandle(file);
+
+ eof_info.EndOfFile.QuadPart = offset;
+
+ status = pNtSetInformationFile(handle,
+ &io_status,
+ &eof_info,
+ sizeof eof_info,
+ FileEndOfFileInformation);
+
+ if (NT_SUCCESS(status)) {
+ SET_REQ_RESULT(req, 0);
+ } else {
+ SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
+ }
}
@@ -706,23 +831,193 @@ void fs__link(uv_fs_t* req, const wchar_t* path, const wchar_t* new_path) {
}
+void fs__create_junction(uv_fs_t* req, const wchar_t* path, const wchar_t* new_path) {
+ HANDLE handle = INVALID_HANDLE_VALUE;
+ REPARSE_DATA_BUFFER *buffer = NULL;
+ int created = 0;
+ int target_len;
+ int is_absolute, is_long_path;
+ int needed_buf_size, used_buf_size, used_data_size, path_buf_len;
+ int start, len, i;
+ int add_slash;
+ DWORD bytes;
+ wchar_t* path_buf;
+
+ target_len = wcslen(path);
+ is_long_path = wcsncmp(path, LONG_PATH_PREFIX, LONG_PATH_PREFIX_LEN) == 0;
+
+ if (is_long_path) {
+ is_absolute = 1;
+ } else {
+ is_absolute = target_len >= 3 && IS_LETTER(path[0]) &&
+ path[1] == L':' && IS_SLASH(path[2]);
+ }
+
+ if (!is_absolute) {
+ /* Not supporting relative paths */
+ SET_REQ_UV_ERROR(req, EINVAL, ERROR_NOT_SUPPORTED);
+ return;
+ }
+
+ // Do a pessimistic calculation of the required buffer size
+ needed_buf_size =
+ FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) +
+ JUNCTION_PREFIX_LEN * sizeof(wchar_t) +
+ 2 * (target_len + 2) * sizeof(wchar_t);
+
+ // Allocate the buffer
+ buffer = (REPARSE_DATA_BUFFER*)malloc(needed_buf_size);
+ if (!buffer) {
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ }
+
+ // Grab a pointer to the part of the buffer where filenames go
+ path_buf = (wchar_t*)&(buffer->MountPointReparseBuffer.PathBuffer);
+ path_buf_len = 0;
+
+ // Copy the substitute (internal) target path
+ start = path_buf_len;
+
+ wcsncpy((wchar_t*)&path_buf[path_buf_len], JUNCTION_PREFIX,
+ JUNCTION_PREFIX_LEN);
+ path_buf_len += JUNCTION_PREFIX_LEN;
+
+ add_slash = 0;
+ for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) {
+ if (IS_SLASH(path[i])) {
+ add_slash = 1;
+ continue;
+ }
+
+ if (add_slash) {
+ path_buf[path_buf_len++] = L'\\';
+ add_slash = 0;
+ }
+
+ path_buf[path_buf_len++] = path[i];
+ }
+ path_buf[path_buf_len++] = L'\\';
+ len = path_buf_len - start;
+
+ // Set the info about the substitute name
+ buffer->MountPointReparseBuffer.SubstituteNameOffset = start * sizeof(wchar_t);
+ buffer->MountPointReparseBuffer.SubstituteNameLength = len * sizeof(wchar_t);
+
+ // Insert null terminator
+ path_buf[path_buf_len++] = L'\0';
+
+ // Copy the print name of the target path
+ start = path_buf_len;
+ add_slash = 0;
+ for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) {
+ if (IS_SLASH(path[i])) {
+ add_slash = 1;
+ continue;
+ }
+
+ if (add_slash) {
+ path_buf[path_buf_len++] = L'\\';
+ add_slash = 0;
+ }
+
+ path_buf[path_buf_len++] = path[i];
+ }
+ len = path_buf_len - start;
+ if (len == 2) {
+ path_buf[path_buf_len++] = L'\\';
+ len++;
+ }
+
+ // Set the info about the print name
+ buffer->MountPointReparseBuffer.PrintNameOffset = start * sizeof(wchar_t);
+ buffer->MountPointReparseBuffer.PrintNameLength = len * sizeof(wchar_t);
+
+ // Insert another null terminator
+ path_buf[path_buf_len++] = L'\0';
+
+ // Calculate how much buffer space was actually used
+ used_buf_size = FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) +
+ path_buf_len * sizeof(wchar_t);
+ used_data_size = used_buf_size -
+ FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer);
+
+ // Put general info in the data buffer
+ buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
+ buffer->ReparseDataLength = used_data_size;
+ buffer->Reserved = 0;
+
+ // Create a new directory
+ if (!CreateDirectoryW(new_path, NULL)) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ goto error;
+ }
+ created = 1;
+
+ // Open the directory
+ handle = CreateFileW(new_path,
+ GENERIC_ALL,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS |
+ FILE_FLAG_OPEN_REPARSE_POINT,
+ NULL);
+ if (handle == INVALID_HANDLE_VALUE) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ goto error;
+ }
+
+ // Create the actual reparse point
+ if (!DeviceIoControl(handle,
+ FSCTL_SET_REPARSE_POINT,
+ buffer,
+ used_buf_size,
+ NULL,
+ 0,
+ &bytes,
+ NULL)) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ goto error;
+ }
+
+ // Clean up
+ CloseHandle(handle);
+ free(buffer);
+
+ SET_REQ_RESULT(req, 0);
+ return;
+
+error:
+ free(buffer);
+
+ if (handle != INVALID_HANDLE_VALUE) {
+ CloseHandle(handle);
+ }
+
+ if (created) {
+ RemoveDirectoryW(new_path);
+ }
+}
+
+
void fs__symlink(uv_fs_t* req, const wchar_t* path, const wchar_t* new_path,
int flags) {
int result;
- if (pCreateSymbolicLinkW) {
+
+ if (flags & UV_FS_SYMLINK_JUNCTION) {
+ fs__create_junction(req, path, new_path);
+ } else if (pCreateSymbolicLinkW) {
result = pCreateSymbolicLinkW(new_path,
path,
flags & UV_FS_SYMLINK_DIR ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) ? 0 : -1;
if (result == -1) {
SET_REQ_WIN32_ERROR(req, GetLastError());
- return;
+ } else {
+ SET_REQ_RESULT(req, result);
}
} else {
SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
- return;
}
-
- SET_REQ_RESULT(req, result);
}
@@ -772,22 +1067,31 @@ void fs__readlink(uv_fs_t* req, const wchar_t* path) {
}
reparse_data = (REPARSE_DATA_BUFFER*)buffer;
- if (reparse_data->ReparseTag != IO_REPARSE_TAG_SYMLINK) {
+ if (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
+ substitute_name = reparse_data->SymbolicLinkReparseBuffer.PathBuffer +
+ (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset /
+ sizeof(wchar_t));
+ substitute_name_length =
+ reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /
+ sizeof(wchar_t);
+ } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
+ substitute_name = reparse_data->MountPointReparseBuffer.PathBuffer +
+ (reparse_data->MountPointReparseBuffer.SubstituteNameOffset /
+ sizeof(wchar_t));
+ substitute_name_length =
+ reparse_data->MountPointReparseBuffer.SubstituteNameLength /
+ sizeof(wchar_t);
+ } else {
result = -1;
/* something is seriously wrong */
SET_REQ_WIN32_ERROR(req, GetLastError());
goto done;
}
- substitute_name = reparse_data->SymbolicLinkReparseBuffer.PathBuffer +
- (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t));
- substitute_name_length =
- reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
-
/* Strip off the leading \??\ from the substitute name buffer.*/
- if (memcmp(substitute_name, L"\\??\\", 8) == 0) {
- substitute_name += 4;
- substitute_name_length -= 4;
+ if (wcsncmp(substitute_name, JUNCTION_PREFIX, JUNCTION_PREFIX_LEN) == 0) {
+ substitute_name += JUNCTION_PREFIX_LEN;
+ substitute_name_length -= JUNCTION_PREFIX_LEN;
}
utf8size = uv_utf16_to_utf8(substitute_name,
@@ -870,8 +1174,10 @@ static DWORD WINAPI uv_fs_thread_proc(void* parameter) {
fs__readdir(req, req->pathw, req->file_flags);
break;
case UV_FS_STAT:
+ fs__stat(req, req->pathw, 0);
+ break;
case UV_FS_LSTAT:
- fs__stat(req, req->pathw);
+ fs__stat(req, req->pathw, 1);
break;
case UV_FS_FSTAT:
fs__fstat(req, req->file);
@@ -1246,7 +1552,7 @@ int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
} else {
uv_fs_req_init_sync(loop, req, UV_FS_STAT);
UTF8_TO_UTF16(path2 ? path2 : path, pathw);
- fs__stat(req, pathw);
+ fs__stat(req, pathw, 0);
if (path2) {
free(path2);
}
@@ -1290,7 +1596,7 @@ int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
} else {
uv_fs_req_init_sync(loop, req, UV_FS_LSTAT);
UTF8_TO_UTF16(path2 ? path2 : path, pathw);
- fs__stat(req, pathw);
+ fs__stat(req, pathw, 1);
if (path2) {
free(path2);
}
@@ -1505,6 +1811,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);
}
@@ -1538,10 +1845,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;
}
diff --git a/deps/uv/src/win/getaddrinfo.c b/deps/uv/src/win/getaddrinfo.c
index 5353c0b5f0..bdfe1bb93c 100644
--- a/deps/uv/src/win/getaddrinfo.c
+++ b/deps/uv/src/win/getaddrinfo.c
@@ -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;
+ /* call OS function on this thread */
+ 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 getaddrinfo completed */
+ 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;
}
diff --git a/deps/uv/src/win/handle.c b/deps/uv/src/win/handle.c
index 797b0716c6..b501143857 100644
--- a/deps/uv/src/win/handle.c
+++ b/deps/uv/src/win/handle.c
@@ -57,27 +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);
+}
- 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;
}
@@ -87,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:
@@ -104,47 +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(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:
@@ -172,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;
@@ -195,6 +186,10 @@ void uv_process_endgames(uv_loop_t* loop) {
uv_udp_endgame(loop, (uv_udp_t*) handle);
break;
+ case UV_POLL:
+ uv_poll_endgame(loop, (uv_poll_t*) handle);
+ break;
+
case UV_TIMER:
uv_timer_endgame(loop, (uv_timer_t*) handle);
break;
diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h
index 7cc469dcdf..362e23f2c2 100644
--- a/deps/uv/src/win/internal.h
+++ b/deps/uv/src/win/internal.h
@@ -31,49 +31,56 @@
/*
- * 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
*/
-/* Private uv_handle flags */
+/* Used by all handles. */
#define UV_HANDLE_CLOSING 0x00000001
#define UV_HANDLE_CLOSED 0x00000002
-#define UV_HANDLE_BOUND 0x00000004
-#define UV_HANDLE_LISTENING 0x00000008
-#define UV_HANDLE_CONNECTION 0x00000010
-#define UV_HANDLE_CONNECTED 0x00000020
-#define UV_HANDLE_READING 0x00000040
-#define UV_HANDLE_ACTIVE 0x00000040
-#define UV_HANDLE_EOF 0x00000080
-#define UV_HANDLE_SHUTTING 0x00000100
-#define UV_HANDLE_SHUT 0x00000200
-#define UV_HANDLE_ENDGAME_QUEUED 0x00000400
-#define UV_HANDLE_BIND_ERROR 0x00001000
-#define UV_HANDLE_IPV6 0x00002000
-#define UV_HANDLE_PIPESERVER 0x00004000
-#define UV_HANDLE_READ_PENDING 0x00008000
-#define UV_HANDLE_UV_ALLOCED 0x00010000
-#define UV_HANDLE_SYNC_BYPASS_IOCP 0x00020000
-#define UV_HANDLE_ZERO_READ 0x00040000
-#define UV_HANDLE_TTY_RAW 0x00080000
+#define UV_HANDLE_ENDGAME_QUEUED 0x00000004
+#define UV_HANDLE_ACTIVE 0x00000010
+
+/* Keep in sync with uv-common.h: */
+#define UV__REF 0x00000020
+#define UV__ACTIVE 0x00000040
+/* 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
+#define UV_HANDLE_LISTENING 0x00000800
+#define UV_HANDLE_CONNECTION 0x00001000
+#define UV_HANDLE_CONNECTED 0x00002000
+#define UV_HANDLE_EOF 0x00004000
+#define UV_HANDLE_SHUTTING 0x00008000
+#define UV_HANDLE_SHUT 0x00010000
+#define UV_HANDLE_READ_PENDING 0x00020000
+#define UV_HANDLE_SYNC_BYPASS_IOCP 0x00040000
+#define UV_HANDLE_ZERO_READ 0x00080000
#define UV_HANDLE_EMULATE_IOCP 0x00100000
-#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x00200000
-#define UV_HANDLE_TTY_SAVED_POSITION 0x00400000
-#define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x00800000
-#define UV_HANDLE_SHARED_TCP_SOCKET 0x01000000
+
+/* Only used by uv_tcp_t handles. */
+#define UV_HANDLE_IPV6 0x01000000
#define UV_HANDLE_TCP_NODELAY 0x02000000
#define UV_HANDLE_TCP_KEEPALIVE 0x04000000
#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_SOCKET 0x40000000
+
+/* Only used by uv_pipe_t handles. */
+#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x01000000
+#define UV_HANDLE_PIPESERVER 0x02000000
+
+/* Only used by uv_tty_t handles. */
+#define UV_HANDLE_TTY_RAW 0x01000000
+#define UV_HANDLE_TTY_SAVED_POSITION 0x02000000
+#define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x04000000
+
+/* Only used by uv_poll_t handles. */
+#define UV_HANDLE_POLL_SLOW 0x02000000
+
void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle);
void uv_process_endgames(uv_loop_t* loop);
@@ -95,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
@@ -142,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,
@@ -150,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
@@ -160,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);
@@ -168,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);
@@ -193,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
@@ -221,6 +265,25 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle);
/*
+ * Poll watchers
+ */
+void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
+ uv_req_t* req);
+
+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
*/
void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle);
@@ -233,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,
@@ -261,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);
/*
@@ -339,6 +402,9 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
int* addr_len, WSAOVERLAPPED *overlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);
+int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info,
+ OVERLAPPED* overlapped);
+
/* Whether ipv6 is supported */
extern int uv_allow_ipv6;
diff --git a/deps/uv/src/win/loop-watcher.c b/deps/uv/src/win/loop-watcher.c
index c597cd99b1..46d184caf0 100644
--- a/deps/uv/src/win/loop-watcher.c
+++ b/deps/uv/src/win/loop-watcher.c
@@ -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; \
} \
diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c
index 35da85e6ed..2b48e38f85 100644
--- a/deps/uv/src/win/pipe.c
+++ b/deps/uv/src/win/pipe.c
@@ -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);
@@ -717,7 +733,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
return -1;
}
- return uv_tcp_import((uv_tcp_t*)client, server->pending_ipc_info.socket_info,
+ return uv_tcp_import((uv_tcp_t*)client, server->pending_ipc_info.socket_info,
server->pending_ipc_info.tcp_connection);
} else {
pipe_client = (uv_pipe_t*)client;
@@ -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;
}
diff --git a/deps/uv/src/win/poll.c b/deps/uv/src/win/poll.c
new file mode 100644
index 0000000000..c6d68ffd4b
--- /dev/null
+++ b/deps/uv/src/win/poll.c
@@ -0,0 +1,620 @@
+/* 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"
+
+#include <assert.h>
+#include <io.h>
+
+
+static const GUID uv_msafd_provider_ids[UV_MSAFD_PROVIDER_COUNT] = {
+ {0xe70f1aa0, 0xab8b, 0x11cf,
+ {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
+ {0xf9eab0c0, 0x26d4, 0x11d0,
+ {0xbb, 0xbf, 0x00, 0xaa, 0x00, 0x6c, 0x34, 0xe4}},
+ {0x9fc48064, 0x7298, 0x43e4,
+ {0xb7, 0xbd, 0x18, 0x1f, 0x20, 0x89, 0x79, 0x2a}}
+};
+
+typedef struct uv_single_fd_set_s {
+ unsigned int fd_count;
+ SOCKET fd_array[1];
+} uv_single_fd_set_t;
+
+
+static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
+ uv_req_t* req;
+ AFD_POLL_INFO* afd_poll_info;
+ DWORD result;
+
+ /* Find a yet unsubmitted req to submit. */
+ if (handle->submitted_events_1 == 0) {
+ req = &handle->poll_req_1;
+ afd_poll_info = &handle->afd_poll_info_1;
+ handle->submitted_events_1 = handle->events;
+ handle->mask_events_1 = 0;
+ handle->mask_events_2 = handle->events;
+ } else if (handle->submitted_events_2 == 0) {
+ req = &handle->poll_req_2;
+ afd_poll_info = &handle->afd_poll_info_2;
+ handle->submitted_events_2 = handle->events;
+ handle->mask_events_1 = handle->events;
+ handle->mask_events_2 = 0;
+ } else {
+ assert(0);
+ }
+
+ /* Setting Exclusive to TRUE makes the other poll request return if there */
+ /* is any. */
+ afd_poll_info->Exclusive = TRUE;
+ afd_poll_info->NumberOfHandles = 1;
+ afd_poll_info->Timeout.QuadPart = INT64_MAX;
+ afd_poll_info->Handles[0].Handle = (HANDLE) handle->socket;
+ afd_poll_info->Handles[0].Status = 0;
+ afd_poll_info->Handles[0].Events = 0;
+
+ if (handle->events & UV_READABLE) {
+ afd_poll_info->Handles[0].Events |= AFD_POLL_RECEIVE |
+ AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT;
+ }
+ if (handle->events & UV_WRITABLE) {
+ afd_poll_info->Handles[0].Events |= AFD_POLL_SEND | AFD_POLL_CONNECT_FAIL;
+ }
+
+ memset(&req->overlapped, 0, sizeof req->overlapped);
+
+ result = uv_msafd_poll((SOCKET) handle->peer_socket,
+ afd_poll_info,
+ &req->overlapped);
+ if (result != 0 && WSAGetLastError() != WSA_IO_PENDING) {
+ /* Queue this req, reporting an error. */
+ SET_REQ_ERROR(req, WSAGetLastError());
+ uv_insert_pending_req(loop, req);
+ }
+}
+
+
+static int uv__fast_poll_cancel_poll_reqs(uv_loop_t* loop, uv_poll_t* handle) {
+ AFD_POLL_INFO afd_poll_info;
+ DWORD result;
+ HANDLE event;
+ OVERLAPPED overlapped;
+
+ event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (event == NULL) {
+ uv__set_sys_error(loop, GetLastError());
+ return -1;
+ }
+
+ afd_poll_info.Exclusive = TRUE;
+ afd_poll_info.NumberOfHandles = 1;
+ afd_poll_info.Timeout.QuadPart = INT64_MAX;
+ afd_poll_info.Handles[0].Handle = (HANDLE) handle->socket;
+ afd_poll_info.Handles[0].Status = 0;
+ afd_poll_info.Handles[0].Events = AFD_POLL_ALL;
+
+ memset(&overlapped, 0, sizeof overlapped);
+ overlapped.hEvent = (HANDLE) ((uintptr_t) event & 1);
+
+ result = uv_msafd_poll(handle->socket,
+ &afd_poll_info,
+ &overlapped);
+
+ if (result == SOCKET_ERROR) {
+ DWORD error = WSAGetLastError();
+ if (error != WSA_IO_PENDING) {
+ uv__set_sys_error(loop, WSAGetLastError());
+ CloseHandle(event);
+ return -1;
+ }
+ }
+
+ CloseHandle(event);
+ return 0;
+}
+
+
+static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
+ uv_req_t* req) {
+ unsigned char mask_events;
+ AFD_POLL_INFO* afd_poll_info;
+
+ if (req == &handle->poll_req_1) {
+ afd_poll_info = &handle->afd_poll_info_1;
+ handle->submitted_events_1 = 0;
+ mask_events = handle->mask_events_1;
+ } else if (req == &handle->poll_req_2) {
+ afd_poll_info = &handle->afd_poll_info_2;
+ handle->submitted_events_2 = 0;
+ mask_events = handle->mask_events_2;
+ } else {
+ assert(0);
+ }
+
+ /* Report an error unless the select was just interrupted. */
+ if (!REQ_SUCCESS(req)) {
+ DWORD error = GET_REQ_SOCK_ERROR(req);
+ if (error != WSAEINTR && handle->events != 0) {
+ handle->events = 0; /* Stop the watcher */
+ uv__set_sys_error(loop, error);
+ handle->poll_cb(handle, -1, 0);
+ }
+
+ } else if (afd_poll_info->NumberOfHandles >= 1) {
+ unsigned char events = 0;
+
+ if ((afd_poll_info->Handles[0].Events & (AFD_POLL_RECEIVE |
+ AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT)) != 0) {
+ events |= UV_READABLE;
+ }
+ if ((afd_poll_info->Handles[0].Events & (AFD_POLL_SEND |
+ AFD_POLL_CONNECT_FAIL)) != 0) {
+ events |= UV_WRITABLE;
+ }
+
+ events &= handle->events & ~mask_events;
+
+ if (afd_poll_info->Handles[0].Events & AFD_POLL_LOCAL_CLOSE) {
+ /* Stop polling. */
+ handle->events = 0;
+ }
+
+ if (events != 0) {
+ handle->poll_cb(handle, 0, events);
+ }
+ }
+
+ if ((handle->events & ~(handle->submitted_events_1 |
+ handle->submitted_events_2)) != 0) {
+ uv__fast_poll_submit_poll_req(loop, handle);
+ } else if ((handle->flags & UV_HANDLE_CLOSING) &&
+ handle->submitted_events_1 == 0 &&
+ handle->submitted_events_2 == 0) {
+ uv_want_endgame(loop, (uv_handle_t*) handle);
+ }
+}
+
+
+static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
+ assert(handle->type == UV_POLL);
+ assert(!(handle->flags & UV_HANDLE_CLOSING));
+ 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);
+ }
+
+ return 0;
+}
+
+
+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) {
+ uv_want_endgame(loop, (uv_handle_t*) handle);
+ } else {
+ /* Try to cancel outstanding poll requests. */
+ if (pCancelIoEx) {
+ /* Use CancelIoEx to cancel poll requests if available. */
+ if (handle->submitted_events_1)
+ pCancelIoEx((HANDLE) handle->socket, &handle->poll_req_1.overlapped);
+ if (handle->submitted_events_2)
+ pCancelIoEx((HANDLE) handle->socket, &handle->poll_req_2.overlapped);
+ } else if (handle->submitted_events_1 | handle->submitted_events_2) {
+ /* Execute another unique poll to force the others to return. */
+ uv__fast_poll_cancel_poll_reqs(loop, handle);
+ }
+ }
+}
+
+
+static SOCKET uv__fast_poll_create_peer_socket(HANDLE iocp,
+ WSAPROTOCOL_INFOW* protocol_info) {
+ SOCKET sock = 0;
+
+ sock = WSASocketW(protocol_info->iAddressFamily,
+ protocol_info->iSocketType,
+ protocol_info->iProtocol,
+ protocol_info,
+ 0,
+ WSA_FLAG_OVERLAPPED);
+ if (sock == INVALID_SOCKET) {
+ return INVALID_SOCKET;
+ }
+
+ if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) {
+ goto error;
+ };
+
+ if (CreateIoCompletionPort((HANDLE) sock,
+ iocp,
+ (ULONG_PTR) sock,
+ 0) == NULL) {
+ goto error;
+ }
+
+ return sock;
+
+ error:
+ closesocket(sock);
+ return INVALID_SOCKET;
+}
+
+
+static SOCKET uv__fast_poll_get_peer_socket(uv_loop_t* loop,
+ WSAPROTOCOL_INFOW* protocol_info) {
+ int index, i;
+ SOCKET peer_socket;
+
+ index = -1;
+ for (i = 0; i < ARRAY_SIZE(uv_msafd_provider_ids); i++) {
+ if (memcmp((void*) &protocol_info->ProviderId,
+ (void*) &uv_msafd_provider_ids[i],
+ sizeof protocol_info->ProviderId) == 0) {
+ index = i;
+ }
+ }
+
+ /* Check if the protocol uses an msafd socket. */
+ if (index < 0) {
+ return INVALID_SOCKET;
+ }
+
+ /* If we didn't (try) to create a peer socket yet, try to make one. Don't */
+ /* try again if the peer socket creation failed earlier for the same */
+ /* protocol. */
+ peer_socket = loop->poll_peer_sockets[index];
+ if (peer_socket == 0) {
+ peer_socket = uv__fast_poll_create_peer_socket(loop->iocp, protocol_info);
+ loop->poll_peer_sockets[index] = peer_socket;
+ }
+
+ return peer_socket;
+}
+
+
+static DWORD WINAPI uv__slow_poll_thread_proc(void* arg) {
+ uv_req_t* req = (uv_req_t*) arg;
+ uv_poll_t* handle = (uv_poll_t*) req->data;
+ unsigned char events, reported_events;
+ int r;
+ uv_single_fd_set_t rfds, wfds, efds;
+ struct timeval timeout;
+
+ assert(handle->type == UV_POLL);
+ assert(req->type == UV_POLL_REQ);
+
+ if (req == &handle->poll_req_1) {
+ events = handle->submitted_events_1;
+ } else if (req == &handle->poll_req_2) {
+ events = handle->submitted_events_2;
+ } else {
+ assert(0);
+ }
+
+ if (handle->events & UV_READABLE) {
+ rfds.fd_count = 1;
+ rfds.fd_array[0] = handle->socket;
+ } else {
+ rfds.fd_count = 0;
+ }
+
+ if (handle->events & UV_WRITABLE) {
+ wfds.fd_count = 1;
+ wfds.fd_array[0] = handle->socket;
+ efds.fd_count = 1;
+ efds.fd_array[0] = handle->socket;
+ } else {
+ wfds.fd_count = 0;
+ efds.fd_count = 0;
+ }
+
+ /* Make the select() time out after 3 minutes. If select() hangs because */
+ /* the user closed the socket, we will at least not hang indefinitely. */
+ timeout.tv_sec = 3 * 60;
+ timeout.tv_usec = 0;
+
+ r = select(1, (fd_set*) &rfds, (fd_set*) &wfds, (fd_set*) &efds, &timeout);
+ if (r == SOCKET_ERROR) {
+ /* Queue this req, reporting an error. */
+ SET_REQ_ERROR(&handle->poll_req_1, WSAGetLastError());
+ POST_COMPLETION_FOR_REQ(handle->loop, req);
+ return 0;
+ }
+
+ reported_events = 0;
+
+ if (r > 0) {
+ if (rfds.fd_count > 0) {
+ assert(rfds.fd_count == 1);
+ assert(rfds.fd_array[0] == handle->socket);
+ reported_events |= UV_READABLE;
+ }
+
+ if (wfds.fd_count > 0) {
+ assert(wfds.fd_count == 1);
+ assert(wfds.fd_array[0] == handle->socket);
+ reported_events |= UV_WRITABLE;
+ } else if (efds.fd_count > 0) {
+ assert(efds.fd_count == 1);
+ assert(efds.fd_array[0] == handle->socket);
+ reported_events |= UV_WRITABLE;
+ }
+ }
+
+ SET_REQ_SUCCESS(req);
+ req->overlapped.InternalHigh = (DWORD) reported_events;
+ POST_COMPLETION_FOR_REQ(handle->loop, req);
+
+ return 0;
+}
+
+
+static void uv__slow_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
+ uv_req_t* req;
+
+ /* Find a yet unsubmitted req to submit. */
+ if (handle->submitted_events_1 == 0) {
+ req = &handle->poll_req_1;
+ handle->submitted_events_1 = handle->events;
+ handle->mask_events_1 = 0;
+ handle->mask_events_2 = handle->events;
+ } else if (handle->submitted_events_2 == 0) {
+ req = &handle->poll_req_2;
+ handle->submitted_events_2 = handle->events;
+ handle->mask_events_1 = handle->events;
+ handle->mask_events_2 = 0;
+ } else {
+ assert(0);
+ }
+
+ if (!QueueUserWorkItem(uv__slow_poll_thread_proc,
+ (void*) req,
+ WT_EXECUTELONGFUNCTION)) {
+ /* Make this req pending, reporting an error. */
+ SET_REQ_ERROR(req, GetLastError());
+ uv_insert_pending_req(loop, req);
+ }
+}
+
+
+
+static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
+ uv_req_t* req) {
+ unsigned char mask_events;
+ if (req == &handle->poll_req_1) {
+ handle->submitted_events_1 = 0;
+ mask_events = handle->mask_events_1;
+ } else if (req == &handle->poll_req_2) {
+ handle->submitted_events_2 = 0;
+ mask_events = handle->mask_events_2;
+ } else {
+ assert(0);
+ }
+
+ if (!REQ_SUCCESS(req)) {
+ /* Error. */
+ if (handle->events != 0) {
+ handle->events = 0; /* Stop the watcher */
+ uv__set_sys_error(loop, GET_REQ_ERROR(req));
+ handle->poll_cb(handle, -1, 0);
+ }
+ } else {
+ /* Got some events. */
+ int events = req->overlapped.InternalHigh & handle->events & ~mask_events;
+ if (events != 0) {
+ handle->poll_cb(handle, 0, events);
+ }
+ }
+
+ if ((handle->events & ~(handle->submitted_events_1 |
+ handle->submitted_events_2)) != 0) {
+ uv__slow_poll_submit_poll_req(loop, handle);
+ } else if ((handle->flags & UV_HANDLE_CLOSING) &&
+ handle->submitted_events_1 == 0 &&
+ handle->submitted_events_2 == 0) {
+ uv_want_endgame(loop, (uv_handle_t*) handle);
+ }
+}
+
+
+static int uv__slow_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
+ assert(handle->type == UV_POLL);
+ assert(!(handle->flags & UV_HANDLE_CLOSING));
+ 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);
+ }
+
+ return 0;
+}
+
+
+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) {
+ uv_want_endgame(loop, (uv_handle_t*) handle);
+ }
+}
+
+
+int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
+ return uv_poll_init_socket(loop, handle, (SOCKET) _get_osfhandle(fd));
+}
+
+
+int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
+ uv_os_sock_t socket) {
+ WSAPROTOCOL_INFOW protocol_info;
+ int len;
+ SOCKET peer_socket, base_socket;
+ DWORD bytes;
+
+ /* Try to obtain a base handle for the socket. This increases this chances */
+ /* that we find an AFD handle and are able to use the fast poll mechanism. */
+ /* This will always fail on windows XP/2k3, since they don't support the */
+ /* SIO_BASE_HANDLE ioctl. */
+#ifndef NDEBUG
+ base_socket = INVALID_SOCKET;
+#endif
+
+ if (WSAIoctl(socket,
+ SIO_BASE_HANDLE,
+ NULL,
+ 0,
+ &base_socket,
+ sizeof base_socket,
+ &bytes,
+ NULL,
+ NULL) == 0) {
+ assert(base_socket != 0 && base_socket != INVALID_SOCKET);
+ socket = base_socket;
+ }
+
+ uv_handle_init(loop, (uv_handle_t*) handle);
+ handle->type = UV_POLL;
+ handle->socket = socket;
+ handle->events = 0;
+
+ /* Obtain protocol information about the socket. */
+ len = sizeof protocol_info;
+ if (getsockopt(socket,
+ SOL_SOCKET,
+ SO_PROTOCOL_INFOW,
+ (char*) &protocol_info,
+ &len) != 0) {
+ uv__set_sys_error(loop, WSAGetLastError());
+ return -1;
+ }
+
+ /* Get the peer socket that is needed to enable fast poll. If the returned */
+ /* value is NULL, the protocol is not implemented by MSAFD and we'll have */
+ /* to use slow mode. */
+ peer_socket = uv__fast_poll_get_peer_socket(loop, &protocol_info);
+
+ if (peer_socket != INVALID_SOCKET) {
+ /* Initialize fast poll specific fields. */
+ handle->peer_socket = peer_socket;
+ } else {
+ /* Initialize slow poll specific fields. */
+ handle->flags |= UV_HANDLE_POLL_SLOW;
+ }
+
+ /* Intialize 2 poll reqs. */
+ handle->submitted_events_1 = 0;
+ uv_req_init(loop, (uv_req_t*) &(handle->poll_req_1));
+ handle->poll_req_1.type = UV_POLL_REQ;
+ handle->poll_req_1.data = handle;
+
+ handle->submitted_events_2 = 0;
+ uv_req_init(loop, (uv_req_t*) &(handle->poll_req_2));
+ handle->poll_req_2.type = UV_POLL_REQ;
+ handle->poll_req_2.data = handle;
+
+ loop->counters.poll_init++;
+
+ return 0;
+}
+
+
+int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb) {
+ if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {
+ if (uv__fast_poll_set(handle->loop, handle, events) < 0)
+ return -1;
+ } else {
+ if (uv__slow_poll_set(handle->loop, handle, events) < 0)
+ return -1;
+ }
+
+ handle->poll_cb = cb;
+
+ return 0;
+}
+
+
+int uv_poll_stop(uv_poll_t* handle) {
+ if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {
+ return uv__fast_poll_set(handle->loop, handle, 0);
+ } else {
+ return uv__slow_poll_set(handle->loop, handle, 0);
+ }
+}
+
+
+void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) {
+ if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {
+ uv__fast_poll_process_poll_req(loop, handle, req);
+ } else {
+ uv__slow_poll_process_poll_req(loop, handle, req);
+ }
+}
+
+
+void uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
+ if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {
+ uv__fast_poll_close(loop, handle);
+ } else {
+ uv__slow_poll_close(loop, handle);
+ }
+}
+
+
+void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) {
+ assert(handle->flags & UV_HANDLE_CLOSING);
+ assert(!(handle->flags & UV_HANDLE_CLOSED));
+
+ assert(handle->submitted_events_1 == 0);
+ assert(handle->submitted_events_2 == 0);
+
+ handle->flags |= UV_HANDLE_CLOSED;
+ uv__handle_stop(handle);
+
+ if (handle->close_cb) {
+ handle->close_cb((uv_handle_t*)handle);
+ }
+}
diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c
index aacb06176a..481b945c97 100644
--- a/deps/uv/src/win/process.c
+++ b/deps/uv/src/win/process.c
@@ -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,30 +685,28 @@ 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)) {
- 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. */
+ 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;
}
+ /* 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) {
handle->exit_cb(handle, exit_code, handle->exit_signal);
@@ -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;
diff --git a/deps/uv/src/win/req.c b/deps/uv/src/win/req.c
index 65aa6c1581..1aae70911c 100644
--- a/deps/uv/src/win/req.c
+++ b/deps/uv/src/win/req.c
@@ -22,7 +22,6 @@
#include <assert.h>
#include "uv.h"
-#include "../uv-common.h"
#include "internal.h"
@@ -135,6 +134,10 @@ void uv_process_reqs(uv_loop_t* loop) {
uv_process_async_wakeup_req(loop, (uv_async_t*) req->data, req);
break;
+ case UV_POLL_REQ:
+ uv_process_poll_req(loop, (uv_poll_t*) req->data, req);
+ break;
+
case UV_ARES_EVENT_REQ:
uv_process_ares_event_req(loop, (uv_ares_action_t*) req->data, req);
break;
@@ -143,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:
diff --git a/deps/uv/src/win/stream.c b/deps/uv/src/win/stream.c
index 4275bce195..dad8669b1d 100644
--- a/deps/uv/src/win/stream.c
+++ b/deps/uv/src/win/stream.c
@@ -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);
diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c
index 51ef604eb1..fd956a09c6 100644
--- a/deps/uv/src/win/tcp.c
+++ b/deps/uv/src/win/tcp.c
@@ -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);
}
}
@@ -310,10 +309,10 @@ int uv__tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr) {
static void CALLBACK post_completion(void* context, BOOLEAN timed_out) {
- uv_tcp_accept_t* req;
+ uv_req_t* req;
uv_tcp_t* handle;
- req = (uv_tcp_accept_t*) context;
+ req = (uv_req_t*) context;
assert(req != NULL);
handle = (uv_tcp_t*)req->data;
assert(handle != NULL);
@@ -328,6 +327,25 @@ static void CALLBACK post_completion(void* context, BOOLEAN timed_out) {
}
+static void CALLBACK post_write_completion(void* context, BOOLEAN timed_out) {
+ uv_write_t* req;
+ uv_tcp_t* handle;
+
+ req = (uv_write_t*) context;
+ assert(req != NULL);
+ handle = (uv_tcp_t*)req->handle;
+ assert(handle != NULL);
+ assert(!timed_out);
+
+ if (!PostQueuedCompletionStatus(handle->loop->iocp,
+ req->overlapped.InternalHigh,
+ 0,
+ &req->overlapped)) {
+ uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
+ }
+}
+
+
static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
uv_loop_t* loop = handle->loop;
BOOL success;
@@ -381,7 +399,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
req->wait_handle == INVALID_HANDLE_VALUE &&
!RegisterWaitForSingleObject(&req->wait_handle,
- req->overlapped.hEvent, post_completion, (void*) req,
+ req->event_handle, post_completion, (void*) req,
INFINITE, WT_EXECUTEINWAITTHREAD)) {
SET_REQ_ERROR(req, GetLastError());
uv_insert_pending_req(loop, (uv_req_t*)req);
@@ -460,7 +478,7 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
req->wait_handle == INVALID_HANDLE_VALUE &&
!RegisterWaitForSingleObject(&req->wait_handle,
- req->overlapped.hEvent, post_completion, (void*) req,
+ req->event_handle, post_completion, (void*) req,
INFINITE, WT_EXECUTEINWAITTHREAD)) {
SET_REQ_ERROR(req, GetLastError());
uv_insert_pending_req(loop, (uv_req_t*)req);
@@ -481,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;
@@ -505,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;
@@ -623,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. */
@@ -683,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;
@@ -744,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;
@@ -837,6 +866,7 @@ int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle,
uv_fatal_error(GetLastError(), "CreateEvent");
}
req->overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);
+ req->wait_handle = INVALID_HANDLE_VALUE;
}
result = WSASend(handle->socket,
@@ -852,20 +882,19 @@ 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 &&
- req->wait_handle == INVALID_HANDLE_VALUE &&
!RegisterWaitForSingleObject(&req->wait_handle,
- req->overlapped.hEvent, post_completion, (void*) req,
- INFINITE, WT_EXECUTEINWAITTHREAD)) {
+ req->event_handle, post_write_completion, (void*) req,
+ INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) {
SET_REQ_ERROR(req, GetLastError());
uv_insert_pending_req(loop, (uv_req_t*)req);
}
@@ -893,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;
@@ -923,8 +953,12 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
}
} else {
/* Connection closed */
- handle->flags &= ~UV_HANDLE_READING;
+ 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;
@@ -955,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;
@@ -967,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;
@@ -1002,14 +1040,14 @@ 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);
- req->wait_handle = INVALID_HANDLE_VALUE;
}
if (req->event_handle) {
CloseHandle(req->event_handle);
- req->event_handle = NULL;
}
}
@@ -1025,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);
}
@@ -1042,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);
@@ -1079,28 +1117,27 @@ 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) {
- if (REQ_SUCCESS(req)) {
- if (setsockopt(handle->socket,
- SOL_SOCKET,
- SO_UPDATE_CONNECT_CONTEXT,
- NULL,
- 0) == 0) {
- uv_connection_init((uv_stream_t*)handle);
- loop->active_tcp_streams++;
- ((uv_connect_cb)req->cb)(req, 0);
- } else {
- uv__set_sys_error(loop, WSAGetLastError());
- ((uv_connect_cb)req->cb)(req, -1);
- }
+ UNREGISTER_HANDLE_REQ(loop, handle, req);
+
+ if (REQ_SUCCESS(req)) {
+ if (setsockopt(handle->socket,
+ SOL_SOCKET,
+ SO_UPDATE_CONNECT_CONTEXT,
+ NULL,
+ 0) == 0) {
+ uv_connection_init((uv_stream_t*)handle);
+ loop->active_tcp_streams++;
+ ((uv_connect_cb)req->cb)(req, 0);
} else {
- uv__set_sys_error(loop, GET_REQ_SOCK_ERROR(req));
+ uv__set_sys_error(loop, WSAGetLastError());
((uv_connect_cb)req->cb)(req, -1);
}
+ } else {
+ 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);
}
@@ -1132,7 +1169,7 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info,
if (uv_tcp_set_socket(tcp->loop, tcp, socket, 1) != 0) {
return -1;
}
-
+
tcp->loop->active_tcp_streams++;
return 0;
}
@@ -1172,11 +1209,10 @@ 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)) {
- /*
+ /*
* We're about to share the socket with another process. Because
* this is a listening socket, we assume that the other process will
* be accepting connections on it. So, before sharing the socket
@@ -1240,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;
@@ -1259,7 +1295,7 @@ void uv_tcp_close(uv_tcp_t* tcp) {
uv_tcp_non_ifs_lsp_ipv4;
if (!non_ifs_lsp) {
- /*
+ /*
* Shared socket with no non-IFS LSPs, request to cancel pending I/O.
* The socket will be closed inside endgame.
*/
@@ -1269,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);
}
diff --git a/deps/uv/src/win/thread.c b/deps/uv/src/win/thread.c
index d6d3ce8f39..01b8140885 100644
--- a/deps/uv/src/win/thread.c
+++ b/deps/uv/src/win/thread.c
@@ -19,10 +19,11 @@
* IN THE SOFTWARE.
*/
+#include <assert.h>
+
#include "uv.h"
-#include "../uv-common.h"
#include "internal.h"
-#include <assert.h>
+
#define HAVE_SRWLOCK_API() (pTryAcquireSRWLockShared != NULL)
diff --git a/deps/uv/src/win/threadpool.c b/deps/uv/src/win/threadpool.c
index 4fb20d34bc..e066810d53 100644
--- a/deps/uv/src/win/threadpool.c
+++ b/deps/uv/src/win/threadpool.c
@@ -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);
}
diff --git a/deps/uv/src/win/timer.c b/deps/uv/src/win/timer.c
index 555d71ea6d..fbde888d80 100644
--- a/deps/uv/src/win/timer.c
+++ b/deps/uv/src/win/timer.c
@@ -26,12 +26,12 @@
#include "internal.h"
#include "tree.h"
+
#undef NANOSEC
#define NANOSEC 1000000000
/* The resolution of the high-resolution clock. */
-static int64_t uv_ticks_per_msec_ = 0;
static uint64_t uv_hrtime_frequency_ = 0;
static uv_once_t uv_hrtime_init_guard_ = UV_ONCE_INIT;
@@ -112,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;
}
@@ -131,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);
}
}
@@ -153,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");
@@ -171,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;
}
@@ -188,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) {
@@ -198,6 +196,7 @@ int uv_timer_again(uv_timer_t* handle) {
}
handle->flags |= UV_HANDLE_ACTIVE;
+ uv__handle_start(handle);
}
return 0;
@@ -269,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);
diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c
index 5bf90bec24..bd46215e0b 100644
--- a/deps/uv/src/win/tty.c
+++ b/deps/uv/src/win/tty.c
@@ -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) {
- handle->flags &= ~UV_HANDLE_READING;
+ 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;
}
}
@@ -960,9 +969,6 @@ static int uv_tty_reset(uv_tty_t* handle, DWORD* error) {
static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen,
DWORD* error) {
- unsigned short argc = handle->ansi_csi_argc;
- unsigned short* argv = handle->ansi_csi_argv;
-
CONSOLE_SCREEN_BUFFER_INFO info;
COORD start, end;
DWORD count, written;
@@ -1683,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;
@@ -1703,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));
@@ -1716,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);
}
@@ -1726,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);
}
@@ -1736,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) {
@@ -1748,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;
}
@@ -1765,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);
}
}
diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c
index 42069aff9c..ddd08a26e7 100644
--- a/deps/uv/src/win/udp.c
+++ b/deps/uv/src/win/udp.c
@@ -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);
}
diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c
index f4d5fdbea9..10c2271232 100644
--- a/deps/uv/src/win/util.c
+++ b/deps/uv/src/win/util.c
@@ -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>
/*
diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c
index ff6912d0e8..4614a3adae 100644
--- a/deps/uv/src/win/winapi.c
+++ b/deps/uv/src/win/winapi.c
@@ -22,7 +22,6 @@
#include <assert.h>
#include "uv.h"
-#include "../uv-common.h"
#include "internal.h"
@@ -33,6 +32,7 @@ sNtSetInformationFile pNtSetInformationFile;
sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
sCreateSymbolicLinkW pCreateSymbolicLinkW;
+sCancelIoEx pCancelIoEx;
sInitializeSRWLock pInitializeSRWLock;
sAcquireSRWLockShared pAcquireSRWLockShared;
sAcquireSRWLockExclusive pAcquireSRWLockExclusive;
@@ -94,6 +94,9 @@ void uv_winapi_init() {
pCreateSymbolicLinkW = (sCreateSymbolicLinkW)
GetProcAddress(kernel32_module, "CreateSymbolicLinkW");
+ pCancelIoEx = (sCancelIoEx)
+ GetProcAddress(kernel32_module, "CancelIoEx");
+
pInitializeSRWLock = (sInitializeSRWLock)
GetProcAddress(kernel32_module, "InitializeSRWLock");
diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h
index 073b9e8c0c..4b1a249fb3 100644
--- a/deps/uv/src/win/winapi.h
+++ b/deps/uv/src/win/winapi.h
@@ -4141,6 +4141,10 @@ typedef struct _FILE_MODE_INFORMATION {
ULONG Mode;
} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;
+typedef struct _FILE_END_OF_FILE_INFORMATION {
+ LARGE_INTEGER EndOfFile;
+} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION;
+
#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010
#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
@@ -4374,6 +4378,10 @@ typedef BOOLEAN (WINAPI* sCreateSymbolicLinkW)
LPCWSTR lpTargetFileName,
DWORD dwFlags);
+typedef BOOL (WINAPI* sCancelIoEx)
+ (HANDLE hFile,
+ LPOVERLAPPED lpOverlapped);
+
typedef VOID (WINAPI* sInitializeSRWLock)
(PSRWLOCK SRWLock);
@@ -4408,6 +4416,7 @@ extern sNtSetInformationFile pNtSetInformationFile;
extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
extern sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
extern sCreateSymbolicLinkW pCreateSymbolicLinkW;
+extern sCancelIoEx pCancelIoEx;
extern sInitializeSRWLock pInitializeSRWLock;
extern sAcquireSRWLockShared pAcquireSRWLockShared;
extern sAcquireSRWLockExclusive pAcquireSRWLockExclusive;
diff --git a/deps/uv/src/win/winsock.c b/deps/uv/src/win/winsock.c
index 667145dd96..2c3e49a103 100644
--- a/deps/uv/src/win/winsock.c
+++ b/deps/uv/src/win/winsock.c
@@ -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;
@@ -468,3 +468,90 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
return SOCKET_ERROR;
}
}
+
+
+int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info,
+ OVERLAPPED* overlapped) {
+ IO_STATUS_BLOCK iosb;
+ IO_STATUS_BLOCK* iosb_ptr;
+ HANDLE event = NULL;
+ void* apc_context;
+ NTSTATUS status;
+ DWORD error;
+
+ if (overlapped != NULL) {
+ /* Overlapped operation. */
+ iosb_ptr = (IO_STATUS_BLOCK*) &overlapped->Internal;
+ event = overlapped->hEvent;
+
+ /* Do not report iocp completion if hEvent is tagged. */
+ if ((uintptr_t) event & 1) {
+ event = (HANDLE)((uintptr_t) event & ~(uintptr_t) 1);
+ apc_context = NULL;
+ } else {
+ apc_context = overlapped;
+ }
+
+ } else {
+ /* Blocking operation. */
+ iosb_ptr = &iosb;
+ event = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (event == NULL) {
+ return SOCKET_ERROR;
+ }
+ apc_context = NULL;
+ }
+
+ iosb_ptr->Status = STATUS_PENDING;
+ status = pNtDeviceIoControlFile((HANDLE) socket,
+ event,
+ NULL,
+ apc_context,
+ iosb_ptr,
+ IOCTL_AFD_POLL,
+ info,
+ sizeof *info,
+ info,
+ sizeof *info);
+
+ if (overlapped == NULL) {
+ /* If this is a blocking operation, wait for the event to become */
+ /* signaled, and then grab the real status from the io status block. */
+ if (status == STATUS_PENDING) {
+ DWORD r = WaitForSingleObject(event, INFINITE);
+
+ if (r == WAIT_FAILED) {
+ DWORD saved_error = GetLastError();
+ CloseHandle(event);
+ WSASetLastError(saved_error);
+ return SOCKET_ERROR;
+ }
+
+ status = iosb.Status;
+ }
+
+ CloseHandle(event);
+ }
+
+ switch (status) {
+ case STATUS_SUCCESS:
+ error = ERROR_SUCCESS;
+ break;
+
+ case STATUS_PENDING:
+ error = WSA_IO_PENDING;
+ break;
+
+ default:
+ error = uv_ntstatus_to_winsock_error(status);
+ break;
+ }
+
+ WSASetLastError(error);
+
+ if (error == ERROR_SUCCESS) {
+ return 0;
+ } else {
+ return SOCKET_ERROR;
+ }
+}
diff --git a/deps/uv/src/win/winsock.h b/deps/uv/src/win/winsock.h
index d070d58092..957d08ec19 100644
--- a/deps/uv/src/win/winsock.h
+++ b/deps/uv/src/win/winsock.h
@@ -43,11 +43,15 @@
#endif
#ifndef IPV6_V6ONLY
- #define IPV6_V6ONLY 27
+# define IPV6_V6ONLY 27
#endif
#ifndef IPV6_HOPLIMIT
- #define IPV6_HOPLIMIT 21
+# define IPV6_HOPLIMIT 21
+#endif
+
+#ifndef SIO_BASE_HANDLE
+# define SIO_BASE_HANDLE 0x48000022
#endif
/*
@@ -81,6 +85,32 @@
#define AFD_OVERLAPPED 0x00000002
#define AFD_IMMEDIATE 0x00000004
+#define AFD_POLL_RECEIVE_BIT 0
+#define AFD_POLL_RECEIVE (1 << AFD_POLL_RECEIVE_BIT)
+#define AFD_POLL_RECEIVE_EXPEDITED_BIT 1
+#define AFD_POLL_RECEIVE_EXPEDITED (1 << AFD_POLL_RECEIVE_EXPEDITED_BIT)
+#define AFD_POLL_SEND_BIT 2
+#define AFD_POLL_SEND (1 << AFD_POLL_SEND_BIT)
+#define AFD_POLL_DISCONNECT_BIT 3
+#define AFD_POLL_DISCONNECT (1 << AFD_POLL_DISCONNECT_BIT)
+#define AFD_POLL_ABORT_BIT 4
+#define AFD_POLL_ABORT (1 << AFD_POLL_ABORT_BIT)
+#define AFD_POLL_LOCAL_CLOSE_BIT 5
+#define AFD_POLL_LOCAL_CLOSE (1 << AFD_POLL_LOCAL_CLOSE_BIT)
+#define AFD_POLL_CONNECT_BIT 6
+#define AFD_POLL_CONNECT (1 << AFD_POLL_CONNECT_BIT)
+#define AFD_POLL_ACCEPT_BIT 7
+#define AFD_POLL_ACCEPT (1 << AFD_POLL_ACCEPT_BIT)
+#define AFD_POLL_CONNECT_FAIL_BIT 8
+#define AFD_POLL_CONNECT_FAIL (1 << AFD_POLL_CONNECT_FAIL_BIT)
+#define AFD_POLL_QOS_BIT 9
+#define AFD_POLL_QOS (1 << AFD_POLL_QOS_BIT)
+#define AFD_POLL_GROUP_QOS_BIT 10
+#define AFD_POLL_GROUP_QOS (1 << AFD_POLL_GROUP_QOS_BIT)
+
+#define AFD_NUM_POLL_EVENTS 11
+#define AFD_POLL_ALL ((1 << AFD_NUM_POLL_EVENTS) - 1)
+
typedef struct _AFD_RECV_DATAGRAM_INFO {
LPWSABUF BufferArray;
ULONG BufferCount;
@@ -105,6 +135,7 @@ typedef struct _AFD_RECV_INFO {
#define AFD_RECEIVE 5
#define AFD_RECEIVE_DATAGRAM 6
+#define AFD_POLL 9
#define IOCTL_AFD_RECEIVE \
_AFD_CONTROL_CODE(AFD_RECEIVE, METHOD_NEITHER)
@@ -112,8 +143,10 @@ typedef struct _AFD_RECV_INFO {
#define IOCTL_AFD_RECEIVE_DATAGRAM \
_AFD_CONTROL_CODE(AFD_RECEIVE_DATAGRAM, METHOD_NEITHER)
-#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+#define IOCTL_AFD_POLL \
+ _AFD_CONTROL_CODE(AFD_POLL, METHOD_BUFFERED)
+#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
typedef struct _IP_ADAPTER_UNICAST_ADDRESS_XP {
/* FIXME: __C89_NAMELESS was removed */
/* __C89_NAMELESS */ union {