summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2012-06-06 05:21:07 +0200
committerBen Noordhuis <info@bnoordhuis.nl>2012-06-06 05:31:08 +0200
commit5f411405356cd184560507ce870a664e4ef5417f (patch)
tree0befd01d900559c9eac032de763691fba8aa6f2e
parent28e851c169ad589a7f6a1357fd84fd75254a2ab7 (diff)
downloadnode-5f411405356cd184560507ce870a664e4ef5417f.tar.gz
deps: upgrade libuv to 649ad50
-rw-r--r--deps/uv/include/uv-private/ev.h2
-rw-r--r--deps/uv/src/unix/core.c39
-rw-r--r--deps/uv/src/unix/ev/ev.c103
-rw-r--r--deps/uv/src/uv-common.c45
-rw-r--r--deps/uv/src/win/util.c91
5 files changed, 219 insertions, 61 deletions
diff --git a/deps/uv/include/uv-private/ev.h b/deps/uv/include/uv-private/ev.h
index 7709bc349..11e81cda5 100644
--- a/deps/uv/include/uv-private/ev.h
+++ b/deps/uv/include/uv-private/ev.h
@@ -623,7 +623,7 @@ enum {
};
#if EV_PROTOTYPES
-void ev_run (EV_P_ ev_tstamp waittime);
+void ev_run (EV_P_ int flags EV_CPP (= 0));
void ev_break (EV_P_ int how EV_CPP (= EVBREAK_ONE)); /* break out of the loop */
/*
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index 37d03d3eb..b33a6f74c 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -226,16 +226,6 @@ void uv_loop_delete(uv_loop_t* loop) {
}
-static void uv__poll(uv_loop_t* loop, unsigned int timeout) {
- /* bump the loop's refcount, otherwise libev does
- * a zero timeout poll and we end up busy looping
- */
- ev_ref(loop->ev);
- ev_run(loop->ev, timeout / 1000.);
- ev_unref(loop->ev);
-}
-
-
static unsigned int uv__poll_timeout(uv_loop_t* loop) {
if (!uv__has_active_handles(loop))
return 0;
@@ -247,22 +237,22 @@ static unsigned int uv__poll_timeout(uv_loop_t* loop) {
}
+static void uv__poll(uv_loop_t* loop) {
+ void ev__run(EV_P_ ev_tstamp waittime);
+ ev_invoke_pending(loop->ev);
+ ev__run(loop->ev, uv__poll_timeout(loop) / 1000.);
+ ev_invoke_pending(loop->ev);
+}
+
+
static int uv__run(uv_loop_t* loop) {
uv_update_time(loop);
uv__run_timers(loop);
uv__run_idle(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__poll_timeout(loop));
- uv__run_check(loop);
- }
-
+ uv__run_prepare(loop);
+ uv__poll(loop);
+ uv__run_check(loop);
uv__run_closing_handles(loop);
-
return uv__has_active_handles(loop) || uv__has_active_reqs(loop);
}
@@ -604,13 +594,6 @@ static void uv__io_rw(struct ev_loop* ev, ev_io* w, int events) {
uv__io_t* handle = container_of(w, uv__io_t, io_watcher);
u.data = handle->io_watcher.data;
u.cb(loop, handle, events & (EV_READ|EV_WRITE|EV_ERROR));
-
- /* The callback may have closed all active handles. Stop libev from entering
- * the epoll_wait/kevent/port_getn/etc. syscall if that's the case, it would
- * hang indefinitely.
- */
- if (loop->active_handles == 0)
- ev_break(loop->ev, EVBREAK_ONE);
}
diff --git a/deps/uv/src/unix/ev/ev.c b/deps/uv/src/unix/ev/ev.c
index a722981bf..9888277b8 100644
--- a/deps/uv/src/unix/ev/ev.c
+++ b/deps/uv/src/unix/ev/ev.c
@@ -2389,7 +2389,7 @@ time_update (EV_P_ ev_tstamp max_block)
}
void
-ev_run (EV_P_ ev_tstamp waittime)
+ev_run (EV_P_ int flags)
{
#if EV_FEATURE_API
++loop_depth;
@@ -2426,6 +2426,15 @@ ev_run (EV_P_ ev_tstamp waittime)
}
#endif
+#if EV_PREPARE_ENABLE
+ /* queue prepare watchers (and execute them) */
+ if (expect_false (preparecnt))
+ {
+ queue_events (EV_A_ (W *)prepares, preparecnt, EV_PREPARE);
+ EV_INVOKE_PENDING;
+ }
+#endif
+
if (expect_false (loop_done))
break;
@@ -2436,16 +2445,90 @@ ev_run (EV_P_ ev_tstamp waittime)
/* update fd-related kernel structures */
fd_reify (EV_A);
+ /* calculate blocking time */
+ {
+ ev_tstamp waittime = 0.;
+ ev_tstamp sleeptime = 0.;
+
+ /* remember old timestamp for io_blocktime calculation */
+ ev_tstamp prev_mn_now = mn_now;
+
+ /* update time to cancel out callback processing overhead */
+ time_update (EV_A_ 1e100);
+
+ if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt)))
+ {
+ waittime = MAX_BLOCKTIME;
+
+ if (timercnt)
+ {
+ ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now + backend_fudge;
+ if (waittime > to) waittime = to;
+ }
+
+#if EV_PERIODIC_ENABLE
+ if (periodiccnt)
+ {
+ ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now + backend_fudge;
+ if (waittime > to) waittime = to;
+ }
+#endif
+
+ /* don't let timeouts decrease the waittime below timeout_blocktime */
+ if (expect_false (waittime < timeout_blocktime))
+ waittime = timeout_blocktime;
+
+ /* extra check because io_blocktime is commonly 0 */
+ if (expect_false (io_blocktime))
+ {
+ sleeptime = io_blocktime - (mn_now - prev_mn_now);
+
+ if (sleeptime > waittime - backend_fudge)
+ sleeptime = waittime - backend_fudge;
+
+ if (expect_true (sleeptime > 0.))
+ {
+ ev_sleep (sleeptime);
+ waittime -= sleeptime;
+ }
+ }
+ }
+
#if EV_FEATURE_API
- ++loop_count;
+ ++loop_count;
+#endif
+ assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */
+ backend_poll (EV_A_ waittime);
+ assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */
+
+ /* update ev_rt_now, do magic */
+ time_update (EV_A_ waittime + sleeptime);
+ }
+
+ /* queue pending timers and reschedule them */
+ timers_reify (EV_A); /* relative timers called last */
+#if EV_PERIODIC_ENABLE
+ periodics_reify (EV_A); /* absolute timers called first */
+#endif
+
+#if EV_IDLE_ENABLE
+ /* queue idle watchers unless other events are pending */
+ idle_reify (EV_A);
+#endif
+
+#if EV_CHECK_ENABLE
+ /* queue check watchers, to be executed first */
+ if (expect_false (checkcnt))
+ queue_events (EV_A_ (W *)checks, checkcnt, EV_CHECK);
#endif
- assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */
- backend_poll (EV_A_ waittime);
- assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */
EV_INVOKE_PENDING;
}
- while (0);
+ while (expect_true (
+ activecnt
+ && !loop_done
+ && !(flags & (EVRUN_ONCE | EVRUN_NOWAIT))
+ ));
if (loop_done == EVBREAK_ONE)
loop_done = EVBREAK_CANCEL;
@@ -2455,6 +2538,14 @@ ev_run (EV_P_ ev_tstamp waittime)
#endif
}
+/* libuv special */
+void
+ev__run (EV_P_ ev_tstamp waittime)
+{
+ fd_reify (EV_A);
+ backend_poll (EV_A_ waittime);
+}
+
void
ev_break (EV_P_ int how)
{
diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c
index 48f850c73..9639634a1 100644
--- a/deps/uv/src/uv-common.c
+++ b/deps/uv/src/uv-common.c
@@ -22,6 +22,7 @@
#include "uv.h"
#include "uv-common.h"
+#include <stdio.h>
#include <assert.h>
#include <stddef.h> /* NULL */
#include <stdlib.h> /* malloc */
@@ -329,6 +330,50 @@ void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
}
+#ifndef NDEBUG
+static void uv__print_handles(uv_loop_t* loop, int only_active) {
+ const char* type;
+ ngx_queue_t* q;
+ uv_handle_t* h;
+
+ if (loop == NULL)
+ loop = uv_default_loop();
+
+ ngx_queue_foreach(q, &loop->handle_queue) {
+ h = ngx_queue_data(q, uv_handle_t, handle_queue);
+
+ if (only_active && !uv__is_active(h))
+ continue;
+
+ switch (h->type) {
+#define X(uc, lc) case UV_##uc: type = #lc; break;
+ UV_HANDLE_TYPE_MAP(X)
+#undef X
+ default: type = "<unknown>";
+ }
+
+ fprintf(stderr,
+ "[%c%c%c] %-8s %p\n",
+ "R-"[!(h->flags & UV__HANDLE_REF)],
+ "A-"[!(h->flags & UV__HANDLE_ACTIVE)],
+ "I-"[!(h->flags & UV__HANDLE_INTERNAL)],
+ type,
+ (void*)h);
+ }
+}
+
+
+void uv_print_all_handles(uv_loop_t* loop) {
+ uv__print_handles(loop, 0);
+}
+
+
+void uv_print_active_handles(uv_loop_t* loop) {
+ uv__print_handles(loop, 1);
+}
+#endif
+
+
void uv_ref(uv_handle_t* handle) {
uv__handle_ref(handle);
}
diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c
index 87a999ff5..be43d50d2 100644
--- a/deps/uv/src/win/util.c
+++ b/deps/uv/src/win/util.c
@@ -154,7 +154,7 @@ int uv_exepath(char* buffer, size_t* size_ptr) {
uv_err_t uv_cwd(char* buffer, size_t size) {
DWORD utf16_len;
- WCHAR utf16_buffer[MAX_PATH + 1];
+ WCHAR utf16_buffer[MAX_PATH];
int r;
if (buffer == NULL || size == 0) {
@@ -164,6 +164,10 @@ uv_err_t uv_cwd(char* buffer, size_t size) {
utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
if (utf16_len == 0) {
return uv__new_sys_error(GetLastError());
+ } else if (utf16_len > MAX_PATH) {
+ /* This should be impossible; however the CRT has a code path to deal */
+ /* with this scenario, so I added a check anyway. */
+ return uv__new_artificial_error(UV_EIO);
}
/* utf16_len contains the length, *not* including the terminating null. */
@@ -195,45 +199,80 @@ uv_err_t uv_cwd(char* buffer, size_t size) {
uv_err_t uv_chdir(const char* dir) {
- uv_err_t err;
- wchar_t* utf16Buffer = NULL;
- size_t utf16Size;
+ WCHAR utf16_buffer[MAX_PATH];
+ size_t utf16_len;
+ WCHAR drive_letter, env_var[4];
- if (!dir) {
- err.code = UV_EINVAL;
- goto done;
+ if (dir == NULL) {
+ return uv__new_artificial_error(UV_EINVAL);
}
- utf16Size = uv_utf8_to_utf16(dir, NULL, 0);
- if (!utf16Size) {
- err = uv__new_sys_error(GetLastError());
- goto done;
+ if (MultiByteToWideChar(CP_UTF8,
+ 0,
+ dir,
+ -1,
+ utf16_buffer,
+ MAX_PATH) == 0) {
+ DWORD error = GetLastError();
+ /* The maximum length of the current working directory is 260 chars, */
+ /* including terminating null. If it doesn't fit, the path name must be */
+ /* too long. */
+ if (error == ERROR_INSUFFICIENT_BUFFER) {
+ return uv__new_artificial_error(UV_ENAMETOOLONG);
+ } else {
+ return uv__new_sys_error(error);
+ }
}
- utf16Buffer = (wchar_t*)malloc(sizeof(wchar_t) * utf16Size);
- if (!utf16Buffer) {
- err.code = UV_ENOMEM;
- goto done;
+ if (!SetCurrentDirectoryW(utf16_buffer)) {
+ return uv__new_sys_error(GetLastError());
}
- if (!uv_utf8_to_utf16(dir, utf16Buffer, utf16Size)) {
- err = uv__new_sys_error(GetLastError());
- goto done;
+ /* Windows stores the drive-local path in an "hidden" environment variable, */
+ /* which has the form "=C:=C:\Windows". SetCurrentDirectory does not */
+ /* update this, so we'll have to do it. */
+ utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
+ if (utf16_len == 0) {
+ return uv__new_sys_error(GetLastError());
+ } else if (utf16_len > MAX_PATH) {
+ return uv__new_artificial_error(UV_EIO);
}
- if (_wchdir(utf16Buffer) == -1) {
- err = uv__new_sys_error(_doserrno);
- goto done;
+ /* The returned directory should not have a trailing slash, unless it */
+ /* points at a drive root, like c:\. Remove it if needed. */
+ if (utf16_buffer[utf16_len - 1] == L'\\' &&
+ !(utf16_len == 3 && utf16_buffer[1] == L':')) {
+ utf16_len--;
+ utf16_buffer[utf16_len] = L'\0';
}
- err = uv_ok_;
+ if (utf16_len < 2 || utf16_buffer[1] != L':') {
+ /* Doesn't look like a drive letter could be there - probably an UNC */
+ /* path. TODO: Need to handle win32 namespaces like \\?\C:\ ? */
+ drive_letter = 0;
+ } else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') {
+ drive_letter = utf16_buffer[0];
+ } else if (utf16_buffer[0] >= L'a' && utf16_buffer[0] <= L'z') {
+ /* Convert to uppercase. */
+ drive_letter = utf16_buffer[0] - L'a' + L'A';
+ } else {
+ /* Not valid. */
+ drive_letter = 0;
+ }
-done:
- if (utf16Buffer) {
- free(utf16Buffer);
+ if (drive_letter != 0) {
+ /* Construct the environment variable name and set it. */
+ env_var[0] = L'=';
+ env_var[1] = drive_letter;
+ env_var[2] = L':';
+ env_var[3] = L'\0';
+
+ if (!SetEnvironmentVariableW(env_var, utf16_buffer)) {
+ return uv__new_sys_error(GetLastError());
+ }
}
- return err;
+ return uv_ok_;
}