summaryrefslogtreecommitdiff
path: root/deps/uv
diff options
context:
space:
mode:
authorBert Belder <bertbelder@gmail.com>2012-08-07 01:25:06 +0200
committerBert Belder <bertbelder@gmail.com>2012-08-07 01:57:56 +0200
commite0a603a4993e995080a8926fcddbbde752a2136e (patch)
tree34a57a6d3217c06550da581635dea57799fba176 /deps/uv
parent9e55ba7d6bbfeaa867e0f151dd27bc0ba034cad7 (diff)
downloadnode-e0a603a4993e995080a8926fcddbbde752a2136e.tar.gz
uv: upgrade to 3a8bb3b
Diffstat (limited to 'deps/uv')
-rw-r--r--deps/uv/LICENSE4
-rw-r--r--deps/uv/README.md6
-rw-r--r--deps/uv/config-mingw.mk8
-rw-r--r--deps/uv/config-unix.mk2
-rw-r--r--deps/uv/include/uv-private/uv-unix.h18
-rw-r--r--deps/uv/include/uv.h20
-rw-r--r--deps/uv/src/inet.c293
-rw-r--r--deps/uv/src/unix/core.c7
-rw-r--r--deps/uv/src/unix/freebsd.c18
-rw-r--r--deps/uv/src/unix/internal.h6
-rw-r--r--deps/uv/src/unix/pipe.c35
-rw-r--r--deps/uv/src/unix/stream.c114
-rw-r--r--deps/uv/src/unix/sunos.c19
-rw-r--r--deps/uv/src/unix/tcp.c180
-rw-r--r--deps/uv/src/unix/thread.c40
-rw-r--r--deps/uv/src/uv-common.c14
-rw-r--r--deps/uv/src/win/error.c1
-rw-r--r--deps/uv/src/win/pipe.c2
-rw-r--r--deps/uv/src/win/tcp.c8
-rw-r--r--deps/uv/src/win/tty.c2
-rw-r--r--deps/uv/test/benchmark-udp-packet-storm.c2
-rw-r--r--deps/uv/test/test-hrtime.c2
-rw-r--r--deps/uv/test/test-list.h2
-rw-r--r--deps/uv/test/test-process-title.c13
-rw-r--r--deps/uv/test/test-shutdown-close.c4
-rw-r--r--deps/uv/test/test-tcp-close-while-connecting.c2
-rw-r--r--deps/uv/test/test-tcp-unexpected-read.c2
-rw-r--r--deps/uv/uv.gyp2
28 files changed, 630 insertions, 196 deletions
diff --git a/deps/uv/LICENSE b/deps/uv/LICENSE
index f62d7f199..57279fc8b 100644
--- a/deps/uv/LICENSE
+++ b/deps/uv/LICENSE
@@ -40,3 +40,7 @@ The externally maintained libraries used by libuv are:
- libeio, located at eio/ is copyright Marc Alexander Lehmann, and
dual-licensed under the MIT license and GPL2.
+
+ - inet_pton and inet_ntop implementations, contained in src/inet.c, are
+ copyright the Internet Systems Consortium, Inc., and licensed under the ISC
+ license.
diff --git a/deps/uv/README.md b/deps/uv/README.md
index f86a0000e..1359742f9 100644
--- a/deps/uv/README.md
+++ b/deps/uv/README.md
@@ -39,8 +39,10 @@ http://nodejs.org/
## Documentation
-See `include/uv.h`.
-
+ * [include/uv.h](https://github.com/joyent/libuv/blob/master/include/uv.h)
+ &mdash; API documentation in the form of detailed header comments.
+ * [An Introduction to libuv](http://nikhilm.github.com/uvbook/) &mdash; An
+ overview of libuv with tutorials.
## Build Instructions
diff --git a/deps/uv/config-mingw.mk b/deps/uv/config-mingw.mk
index 9e49ec71b..8a253bae7 100644
--- a/deps/uv/config-mingw.mk
+++ b/deps/uv/config-mingw.mk
@@ -37,7 +37,7 @@ RUNNER_LINKFLAGS=$(LINKFLAGS)
RUNNER_LIBS=-lws2_32 -lpsapi -liphlpapi
RUNNER_SRC=test/runner-win.c
-uv.a: $(WIN_OBJS) src/cares.o src/fs-poll.o src/uv-common.o $(CARES_OBJS)
+uv.a: $(WIN_OBJS) src/cares.o src/fs-poll.o src/inet.o src/uv-common.o $(CARES_OBJS)
$(AR) rcs uv.a $^
src/%.o: src/%.c include/uv.h include/uv-private/uv-win.h
@@ -46,16 +46,10 @@ src/%.o: src/%.c include/uv.h include/uv-private/uv-win.h
src/win/%.o: src/win/%.c include/uv.h include/uv-private/uv-win.h src/win/internal.h
$(CC) $(CFLAGS) -o $@ -c $<
-EIO_CPPFLAGS += $(CPPFLAGS)
-EIO_CPPFLAGS += -DEIO_STACKSIZE=65536
-EIO_CPPFLAGS += -D_GNU_SOURCE
-
clean-platform:
-rm -f src/ares/*.o
- -rm -f src/eio/*.o
-rm -f src/win/*.o
distclean-platform:
-rm -f src/ares/*.o
- -rm -f src/eio/*.o
-rm -f src/win/*.o
diff --git a/deps/uv/config-unix.mk b/deps/uv/config-unix.mk
index 0581b5114..667e7b94f 100644
--- a/deps/uv/config-unix.mk
+++ b/deps/uv/config-unix.mk
@@ -131,7 +131,7 @@ endif
RUNNER_LIBS=
RUNNER_SRC=test/runner-unix.c
-uv.a: $(OBJS) src/cares.o src/fs-poll.o src/uv-common.o src/unix/ev/ev.o src/unix/uv-eio.o src/unix/eio/eio.o $(CARES_OBJS)
+uv.a: $(OBJS) src/cares.o src/fs-poll.o src/inet.o src/uv-common.o src/unix/ev/ev.o src/unix/uv-eio.o src/unix/eio/eio.o $(CARES_OBJS)
$(AR) rcs uv.a $^
src/%.o: src/%.c include/uv.h include/uv-private/uv-unix.h
diff --git a/deps/uv/include/uv-private/uv-unix.h b/deps/uv/include/uv-private/uv-unix.h
index 31524c04c..a8dda72a2 100644
--- a/deps/uv/include/uv-private/uv-unix.h
+++ b/deps/uv/include/uv-private/uv-unix.h
@@ -40,10 +40,17 @@
#include <termios.h>
#include <pwd.h>
-#include <semaphore.h>
#include <pthread.h>
#include <signal.h>
+#if defined(__APPLE__) && defined(__MACH__)
+# include <mach/mach.h>
+# include <mach/task.h>
+# include <mach/semaphore.h>
+#else
+# include <semaphore.h>
+#endif
+
#if __sun
# include <sys/port.h>
# include <port.h>
@@ -67,7 +74,11 @@ typedef pthread_once_t uv_once_t;
typedef pthread_t uv_thread_t;
typedef pthread_mutex_t uv_mutex_t;
typedef pthread_rwlock_t uv_rwlock_t;
+#if defined(__APPLE__) && defined(__MACH__)
+typedef semaphore_t uv_sem_t;
+#else
typedef sem_t uv_sem_t;
+#endif
/* Platform-specific definitions for uv_spawn support. */
typedef gid_t uv_gid_t;
@@ -173,8 +184,9 @@ struct uv__io_s {
int fd; \
-/* UV_TCP */
-#define UV_TCP_PRIVATE_FIELDS
+/* UV_TCP, idle_handle is for UV_TCP_SINGLE_ACCEPT handles */
+#define UV_TCP_PRIVATE_FIELDS \
+ uv_idle_t* idle_handle; \
/* UV_UDP */
diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h
index 0cdc2eded..1f8becab0 100644
--- a/deps/uv/include/uv.h
+++ b/deps/uv/include/uv.h
@@ -121,7 +121,8 @@ extern "C" {
XX( 54, ENOSPC, "no space left on device") \
XX( 55, EIO, "i/o error") \
XX( 56, EROFS, "read-only file system" ) \
- XX( 57, ENODEV, "no such device" )
+ XX( 57, ENODEV, "no such device" ) \
+ XX( 58, ECANCELED, "operation canceled" )
#define UV_ERRNO_GEN(val, name, s) UV_##name = val,
@@ -427,6 +428,10 @@ UV_EXTERN void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg);
* Note that handles that wrap file descriptors are closed immediately but
* close_cb will still be deferred to the next iteration of the event loop.
* It gives you a chance to free up any resources associated with the handle.
+ *
+ * In-progress requests, like uv_connect_t or uv_write_t, are cancelled and
+ * have their callbacks called asynchronously with status=-1 and the error code
+ * set to UV_ECANCELED.
*/
UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb);
@@ -528,9 +533,12 @@ UV_EXTERN int uv_read2_start(uv_stream_t*, uv_alloc_cb alloc_cb,
* { .base = "4", .len = 1 }
* };
*
+ * uv_write_t req1;
+ * uv_write_t req2;
+ *
* // writes "1234"
- * uv_write(req, stream, a, 2);
- * uv_write(req, stream, b, 2);
+ * uv_write(&req1, stream, a, 2);
+ * uv_write(&req2, stream, b, 2);
*
*/
UV_EXTERN int uv_write(uv_write_t* req, uv_stream_t* handle,
@@ -1614,6 +1622,12 @@ UV_EXTERN struct sockaddr_in6 uv_ip6_addr(const char* ip, int port);
UV_EXTERN int uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size);
UV_EXTERN int uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size);
+/* Cross-platform IPv6-capable implementation of the 'standard' inet_ntop */
+/* and inet_pton functions. On success they return UV_OK. If an error */
+/* the target of the `dst` pointer is unmodified. */
+uv_err_t uv_inet_ntop(int af, const void* src, char* dst, size_t size);
+uv_err_t uv_inet_pton(int af, const char* src, void* dst);
+
/* Gets the executable path */
UV_EXTERN int uv_exepath(char* buffer, size_t* size);
diff --git a/deps/uv/src/inet.c b/deps/uv/src/inet.c
new file mode 100644
index 000000000..293fbf6d2
--- /dev/null
+++ b/deps/uv/src/inet.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "uv.h"
+#include "uv-common.h"
+
+
+static const uv_err_t uv_eafnosupport_ = { UV_EAFNOSUPPORT, 0 };
+static const uv_err_t uv_enospc_ = { UV_ENOSPC, 0 };
+static const uv_err_t uv_einval_ = { UV_EINVAL, 0 };
+
+static uv_err_t inet_ntop4(const unsigned char *src, char *dst, size_t size);
+static uv_err_t inet_ntop6(const unsigned char *src, char *dst, size_t size);
+static uv_err_t inet_pton4(const char *src, unsigned char *dst);
+static uv_err_t inet_pton6(const char *src, unsigned char *dst);
+
+
+uv_err_t uv_inet_ntop(int af, const void* src, char* dst, size_t size) {
+ switch (af) {
+ case AF_INET:
+ return (inet_ntop4(src, dst, size));
+ case AF_INET6:
+ return (inet_ntop6(src, dst, size));
+ default:
+ return uv_eafnosupport_;
+ }
+ /* NOTREACHED */
+}
+
+
+static uv_err_t inet_ntop4(const unsigned char *src, char *dst, size_t size) {
+ static const char fmt[] = "%u.%u.%u.%u";
+ char tmp[sizeof "255.255.255.255"];
+ size_t l;
+
+#ifndef _WIN32
+ l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
+#else
+ l = _snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
+#endif
+ if (l <= 0 || l >= size) {
+ return uv_enospc_;
+ }
+ strncpy(dst, tmp, size);
+ dst[size - 1] = '\0';
+ return uv_ok_;
+}
+
+
+static uv_err_t inet_ntop6(const unsigned char *src, char *dst, size_t size) {
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+ struct { int base, len; } best, cur;
+ unsigned int words[sizeof(struct in6_addr) / sizeof(uint16_t)];
+ int i;
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof words);
+ for (i = 0; i < (int) sizeof(struct in6_addr); i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ best.len = 0;
+ cur.base = -1;
+ cur.len = 0;
+ for (i = 0; i < (int) ARRAY_SIZE(words); i++) {
+ if (words[i] == 0) {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ for (i = 0; i < (int) ARRAY_SIZE(words); i++) {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base &&
+ i < (best.base + best.len)) {
+ if (i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0)
+ *tp++ = ':';
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 && (best.len == 6 ||
+ (best.len == 7 && words[7] != 0x0001) ||
+ (best.len == 5 && words[5] == 0xffff))) {
+ uv_err_t err = inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp));
+ if (err.code != UV_OK)
+ return err;
+ tp += strlen(tp);
+ break;
+ }
+ tp += sprintf(tp, "%x", words[i]);
+ }
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words))
+ *tp++ = ':';
+ *tp++ = '\0';
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((size_t)(tp - tmp) > size) {
+ return uv_enospc_;
+ }
+ strcpy(dst, tmp);
+ return uv_ok_;
+}
+
+
+uv_err_t uv_inet_pton(int af, const char* src, void* dst) {
+ switch (af) {
+ case AF_INET:
+ return (inet_pton4(src, dst));
+ case AF_INET6:
+ return (inet_pton6(src, dst));
+ default:
+ return uv_eafnosupport_;
+ }
+ /* NOTREACHED */
+}
+
+
+static uv_err_t inet_pton4(const char *src, unsigned char *dst) {
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ unsigned char tmp[sizeof(struct in_addr)], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ *(tp = tmp) = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr(digits, ch)) != NULL) {
+ unsigned int nw = *tp * 10 + (pch - digits);
+
+ if (saw_digit && *tp == 0)
+ return uv_einval_;
+ if (nw > 255)
+ return uv_einval_;
+ *tp = nw;
+ if (!saw_digit) {
+ if (++octets > 4)
+ return uv_einval_;
+ saw_digit = 1;
+ }
+ } else if (ch == '.' && saw_digit) {
+ if (octets == 4)
+ return uv_einval_;
+ *++tp = 0;
+ saw_digit = 0;
+ } else
+ return uv_einval_;
+ }
+ if (octets < 4)
+ return uv_einval_;
+ memcpy(dst, tmp, sizeof(struct in_addr));
+ return uv_ok_;
+}
+
+
+static uv_err_t inet_pton6(const char *src, unsigned char *dst) {
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ unsigned char tmp[sizeof(struct in6_addr)], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, seen_xdigits;
+ unsigned int val;
+
+ memset((tp = tmp), '\0', sizeof tmp);
+ endp = tp + sizeof tmp;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return uv_einval_;
+ curtok = src;
+ seen_xdigits = 0;
+ val = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (++seen_xdigits > 4)
+ return uv_einval_;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!seen_xdigits) {
+ if (colonp)
+ return uv_einval_;
+ colonp = tp;
+ continue;
+ } else if (*src == '\0') {
+ return uv_einval_;
+ }
+ if (tp + sizeof(uint16_t) > endp)
+ return uv_einval_;
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ seen_xdigits = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + sizeof(struct in_addr)) <= endp)) {
+ uv_err_t err = inet_pton4(curtok, tp);
+ if (err.code == 0) {
+ tp += sizeof(struct in_addr);
+ seen_xdigits = 0;
+ break; /*%< '\\0' was seen by inet_pton4(). */
+ }
+ }
+ return uv_einval_;
+ }
+ if (seen_xdigits) {
+ if (tp + sizeof(uint16_t) > endp)
+ return uv_einval_;
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ }
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ if (tp == endp)
+ return uv_einval_;
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ return uv_einval_;
+ memcpy(dst, tmp, sizeof tmp);
+ return uv_ok_;
+}
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index 2f8815966..4bc6b77d6 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -69,10 +69,13 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
break;
case UV_TTY:
- case UV_TCP:
uv__stream_close((uv_stream_t*)handle);
break;
+ case UV_TCP:
+ uv__tcp_close((uv_tcp_t*)handle);
+ break;
+
case UV_UDP:
uv__udp_close((uv_udp_t*)handle);
break;
@@ -228,7 +231,7 @@ void uv_loop_delete(uv_loop_t* loop) {
static unsigned int uv__poll_timeout(uv_loop_t* loop) {
- if (!uv__has_active_handles(loop))
+ if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))
return 0;
if (!ngx_queue_empty(&loop->idle_handles))
diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c
index d916b0b12..be8006c5a 100644
--- a/deps/uv/src/unix/freebsd.c
+++ b/deps/uv/src/unix/freebsd.c
@@ -139,9 +139,23 @@ char** uv_setup_args(int argc, char** argv) {
uv_err_t uv_set_process_title(const char* title) {
+ int oid[4];
+
if (process_title) free(process_title);
process_title = strdup(title);
- setproctitle(title);
+
+ oid[0] = CTL_KERN;
+ oid[1] = KERN_PROC;
+ oid[2] = KERN_PROC_ARGS;
+ oid[3] = getpid();
+
+ sysctl(oid,
+ ARRAY_SIZE(oid),
+ NULL,
+ NULL,
+ process_title,
+ strlen(process_title) + 1);
+
return uv_ok_;
}
@@ -261,7 +275,7 @@ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
return uv__new_sys_error(ENOMEM);
}
- if (sysctlbyname("kern.cp_times", &cp_times, &size, NULL, 0) < 0) {
+ if (sysctlbyname("kern.cp_times", cp_times, &size, NULL, 0) < 0) {
free(cp_times);
free(*cpu_infos);
return uv__new_sys_error(errno);
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
index 23f16f7b0..233f74287 100644
--- a/deps/uv/src/unix/internal.h
+++ b/deps/uv/src/unix/internal.h
@@ -93,7 +93,8 @@ enum {
UV_STREAM_WRITABLE = 0x40, /* The stream is writable */
UV_STREAM_BLOCKING = 0x80, /* Synchronous writes. */
UV_TCP_NODELAY = 0x100, /* Disable Nagle. */
- UV_TCP_KEEPALIVE = 0x200 /* Turn on keep-alive. */
+ UV_TCP_KEEPALIVE = 0x200, /* Turn on keep-alive. */
+ UV_TCP_SINGLE_ACCEPT = 0x400 /* Only accept() when idle. */
};
inline static void uv__req_init(uv_loop_t* loop,
@@ -139,8 +140,6 @@ int uv__stream_open(uv_stream_t*, int fd, int flags);
void uv__stream_destroy(uv_stream_t* stream);
void uv__server_io(uv_loop_t* loop, uv__io_t* watcher, int events);
int uv__accept(int sockfd);
-int uv__connect(uv_connect_t* req, uv_stream_t* stream, struct sockaddr* addr,
- socklen_t addrlen, uv_connect_cb cb);
/* tcp */
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb);
@@ -164,6 +163,7 @@ void uv__poll_close(uv_poll_t* handle);
void uv__prepare_close(uv_prepare_t* handle);
void uv__process_close(uv_process_t* handle);
void uv__stream_close(uv_stream_t* handle);
+void uv__tcp_close(uv_tcp_t* handle);
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);
diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c
index 317ac67c1..957e96f8a 100644
--- a/deps/uv/src/unix/pipe.c
+++ b/deps/uv/src/unix/pipe.c
@@ -170,18 +170,17 @@ void uv_pipe_connect(uv_connect_t* req,
uv_connect_cb cb) {
struct sockaddr_un saddr;
int saved_errno;
- int sockfd;
- int status;
+ int new_sock;
+ int err;
int r;
saved_errno = errno;
- sockfd = -1;
- status = -1;
+ new_sock = (handle->fd == -1);
+ err = -1;
- if ((sockfd = uv__socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
- uv__set_sys_error(handle->loop, errno);
- goto out;
- }
+ if (new_sock)
+ if ((handle->fd = uv__socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+ goto out;
memset(&saddr, 0, sizeof saddr);
uv_strlcpy(saddr.sun_path, name, sizeof(saddr.sun_path));
@@ -191,25 +190,25 @@ void uv_pipe_connect(uv_connect_t* req,
* is either there or not.
*/
do {
- r = connect(sockfd, (struct sockaddr*)&saddr, sizeof saddr);
+ r = connect(handle->fd, (struct sockaddr*)&saddr, sizeof saddr);
}
while (r == -1 && errno == EINTR);
- if (r == -1) {
- status = errno;
- close(sockfd);
+ if (r == -1)
goto out;
- }
- uv__stream_open((uv_stream_t*)handle,
- sockfd,
- UV_STREAM_READABLE | UV_STREAM_WRITABLE);
+ if (new_sock)
+ if (uv__stream_open((uv_stream_t*)handle,
+ handle->fd,
+ UV_STREAM_READABLE | UV_STREAM_WRITABLE))
+ goto out;
+
uv__io_start(handle->loop, &handle->read_watcher);
uv__io_start(handle->loop, &handle->write_watcher);
- status = 0;
+ err = 0;
out:
- handle->delayed_error = status; /* Passed to callback. */
+ handle->delayed_error = err ? errno : 0; /* Passed to callback. */
handle->connect_req = req;
uv__req_init(handle->loop, req, UV_CONNECT);
diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index 8c33ee09c..26875a7ca 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -120,7 +120,7 @@ void uv__stream_destroy(uv_stream_t* stream) {
if (stream->connect_req) {
uv__req_unregister(stream->loop, stream->connect_req);
- uv__set_artificial_error(stream->loop, UV_EINTR);
+ uv__set_artificial_error(stream->loop, UV_ECANCELED);
stream->connect_req->cb(stream->connect_req, -1);
stream->connect_req = NULL;
}
@@ -136,7 +136,7 @@ void uv__stream_destroy(uv_stream_t* stream) {
free(req->bufs);
if (req->cb) {
- uv__set_artificial_error(req->handle->loop, UV_EINTR);
+ uv__set_artificial_error(req->handle->loop, UV_ECANCELED);
req->cb(req, -1);
}
}
@@ -156,13 +156,23 @@ void uv__stream_destroy(uv_stream_t* stream) {
if (stream->shutdown_req) {
uv__req_unregister(stream->loop, stream->shutdown_req);
- uv__set_artificial_error(stream->loop, UV_EINTR);
+ uv__set_artificial_error(stream->loop, UV_ECANCELED);
stream->shutdown_req->cb(stream->shutdown_req, -1);
stream->shutdown_req = NULL;
}
}
+static void uv__next_accept(uv_idle_t* idle, int status) {
+ uv_stream_t* stream = idle->data;
+
+ uv_idle_stop(idle);
+
+ if (stream->accepted_fd == -1)
+ uv__io_start(stream->loop, &stream->read_watcher);
+}
+
+
void uv__server_io(uv_loop_t* loop, uv__io_t* w, int events) {
int fd;
uv_stream_t* stream = container_of(w, uv_stream_t, read_watcher);
@@ -198,14 +208,44 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, int events) {
}
} else {
stream->accepted_fd = fd;
- stream->connection_cb((uv_stream_t*)stream, 0);
- if (stream->accepted_fd >= 0) {
+ stream->connection_cb(stream, 0);
+
+ if (stream->accepted_fd != -1 ||
+ (stream->type == UV_TCP && stream->flags == UV_TCP_SINGLE_ACCEPT)) {
/* The user hasn't yet accepted called uv_accept() */
uv__io_stop(stream->loop, &stream->read_watcher);
- return;
+ break;
}
}
}
+
+ if (stream->fd != -1 &&
+ stream->accepted_fd == -1 &&
+ (stream->type == UV_TCP && stream->flags == UV_TCP_SINGLE_ACCEPT))
+ {
+ /* Defer the next accept() syscall to the next event loop tick.
+ * This lets us guarantee fair load balancing in in multi-process setups.
+ * The problem is as follows:
+ *
+ * 1. Multiple processes listen on the same socket.
+ * 2. The OS scheduler commonly gives preference to one process to
+ * avoid task switches.
+ * 3. That process therefore accepts most of the new connections,
+ * leading to a (sometimes very) unevenly distributed load.
+ *
+ * Here is how we mitigate this issue:
+ *
+ * 1. Accept a connection.
+ * 2. Start an idle watcher.
+ * 3. Don't accept new connections until the idle callback fires.
+ *
+ * This works because the callback only fires when there have been
+ * no recent events, i.e. none of the watched file descriptors have
+ * recently been readable or writable.
+ */
+ uv_tcp_t* tcp = (uv_tcp_t*) stream;
+ uv_idle_start(tcp->idle_handle, uv__next_accept);
+ }
}
@@ -784,9 +824,6 @@ static void uv__stream_connect(uv_stream_t* stream) {
if (error == EINPROGRESS)
return;
- if (error == 0)
- uv__io_start(stream->loop, &stream->read_watcher);
-
stream->connect_req = NULL;
uv__req_unregister(stream->loop, req);
@@ -797,65 +834,6 @@ static void uv__stream_connect(uv_stream_t* stream) {
}
-int uv__connect(uv_connect_t* req, uv_stream_t* stream, struct sockaddr* addr,
- socklen_t addrlen, uv_connect_cb cb) {
- int sockfd;
- int r;
-
- if (stream->type != UV_TCP)
- return uv__set_sys_error(stream->loop, ENOTSOCK);
-
- if (stream->connect_req)
- return uv__set_sys_error(stream->loop, EALREADY);
-
- if (stream->fd <= 0) {
- sockfd = uv__socket(addr->sa_family, SOCK_STREAM, 0);
-
- if (sockfd == -1)
- return uv__set_sys_error(stream->loop, errno);
-
- if (uv__stream_open(stream,
- sockfd,
- UV_STREAM_READABLE | UV_STREAM_WRITABLE)) {
- close(sockfd);
- return -1;
- }
- }
-
- stream->delayed_error = 0;
-
- do
- r = connect(stream->fd, addr, addrlen);
- while (r == -1 && errno == EINTR);
-
- if (r == -1) {
- if (errno == EINPROGRESS)
- ; /* not an error */
- else if (errno == ECONNREFUSED)
- /* If we get a ECONNREFUSED wait until the next tick to report the
- * error. Solaris wants to report immediately--other unixes want to
- * wait.
- */
- stream->delayed_error = errno;
- else
- return uv__set_sys_error(stream->loop, errno);
- }
-
- uv__req_init(stream->loop, req, UV_CONNECT);
- req->cb = cb;
- req->handle = stream;
- ngx_queue_init(&req->queue);
- stream->connect_req = req;
-
- uv__io_start(stream->loop, &stream->write_watcher);
-
- if (stream->delayed_error)
- uv__io_feed(stream->loop, &stream->write_watcher, UV__IO_WRITE);
-
- return 0;
-}
-
-
int uv_write2(uv_write_t* req, uv_stream_t* stream, uv_buf_t bufs[], int bufcnt,
uv_stream_t* send_handle, uv_write_cb cb) {
int empty_queue;
diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c
index a33ec9d98..8c626a3a7 100644
--- a/deps/uv/src/unix/sunos.c
+++ b/deps/uv/src/unix/sunos.c
@@ -127,7 +127,7 @@ static void uv__fs_event_rearm(uv_fs_event_t *handle) {
static void uv__fs_event_read(uv_loop_t* loop, uv__io_t* w, int revents) {
- uv_fs_event_t *handle;
+ uv_fs_event_t *handle = NULL;
timespec_t timeout;
port_event_t pe;
int events;
@@ -137,14 +137,23 @@ static void uv__fs_event_read(uv_loop_t* loop, uv__io_t* w, int revents) {
(void) revents;
do {
- /* TODO use port_getn() */
+ uint_t n = 1;
+
+ /*
+ * Note that our use of port_getn() here (and not port_get()) is deliberate:
+ * there is a bug in event ports (Sun bug 6456558) whereby a zeroed timeout
+ * causes port_get() to return success instead of ETIME when there aren't
+ * actually any events (!); by using port_getn() in lieu of port_get(),
+ * we can at least workaround the bug by checking for zero returned events
+ * and treating it as we would ETIME.
+ */
do {
memset(&timeout, 0, sizeof timeout);
- r = port_get(loop->fs_fd, &pe, &timeout);
+ r = port_getn(loop->fs_fd, &pe, 1, &n, &timeout);
}
while (r == -1 && errno == EINTR);
- if (r == -1 && errno == ETIME)
+ if ((r == -1 && errno == ETIME) || n == 0)
break;
handle = (uv_fs_event_t *)pe.portev_user;
@@ -161,7 +170,7 @@ static void uv__fs_event_read(uv_loop_t* loop, uv__io_t* w, int revents) {
}
while (handle->fd != PORT_DELETED);
- if (handle->fd != PORT_DELETED)
+ if (handle != NULL && handle->fd != PORT_DELETED)
uv__fs_event_rearm(handle);
}
diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c
index 07ad2d9ec..d9cbd0b4e 100644
--- a/deps/uv/src/unix/tcp.c
+++ b/deps/uv/src/unix/tcp.c
@@ -22,6 +22,7 @@
#include "uv.h"
#include "internal.h"
+#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
@@ -30,6 +31,27 @@
int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) {
uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP);
loop->counters.tcp_init++;
+ tcp->idle_handle = NULL;
+ return 0;
+}
+
+
+static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) {
+ int sockfd;
+
+ if (handle->fd != -1)
+ return 0;
+
+ sockfd = uv__socket(domain, SOCK_STREAM, 0);
+
+ if (sockfd == -1)
+ return uv__set_sys_error(handle->loop, errno);
+
+ if (uv__stream_open((uv_stream_t*)handle, sockfd, flags)) {
+ close(sockfd);
+ return -1;
+ }
+
return 0;
}
@@ -44,23 +66,8 @@ static int uv__bind(uv_tcp_t* tcp,
saved_errno = errno;
status = -1;
- if (tcp->fd < 0) {
- if ((tcp->fd = uv__socket(domain, SOCK_STREAM, 0)) == -1) {
- uv__set_sys_error(tcp->loop, errno);
- goto out;
- }
-
- if (uv__stream_open((uv_stream_t*)tcp,
- tcp->fd,
- UV_STREAM_READABLE | UV_STREAM_WRITABLE)) {
- close(tcp->fd);
- tcp->fd = -1;
- status = -2;
- goto out;
- }
- }
-
- assert(tcp->fd >= 0);
+ if (maybe_new_socket(tcp, domain, UV_STREAM_READABLE|UV_STREAM_WRITABLE))
+ return -1;
tcp->delayed_error = 0;
if (bind(tcp->fd, addr, addrsize) == -1) {
@@ -79,6 +86,58 @@ out:
}
+static int uv__connect(uv_connect_t* req,
+ uv_tcp_t* handle,
+ struct sockaddr* addr,
+ socklen_t addrlen,
+ uv_connect_cb cb) {
+ int r;
+
+ assert(handle->type == UV_TCP);
+
+ if (handle->connect_req)
+ return uv__set_sys_error(handle->loop, EALREADY);
+
+ if (maybe_new_socket(handle,
+ addr->sa_family,
+ UV_STREAM_READABLE|UV_STREAM_WRITABLE)) {
+ return -1;
+ }
+
+ handle->delayed_error = 0;
+
+ do
+ r = connect(handle->fd, addr, addrlen);
+ while (r == -1 && errno == EINTR);
+
+ if (r == -1) {
+ if (errno == EINPROGRESS)
+ ; /* not an error */
+ else if (errno == ECONNREFUSED)
+ /* If we get a ECONNREFUSED wait until the next tick to report the
+ * error. Solaris wants to report immediately--other unixes want to
+ * wait.
+ */
+ handle->delayed_error = errno;
+ else
+ return uv__set_sys_error(handle->loop, errno);
+ }
+
+ uv__req_init(handle->loop, req, UV_CONNECT);
+ req->cb = cb;
+ req->handle = (uv_stream_t*) handle;
+ ngx_queue_init(&req->queue);
+ handle->connect_req = req;
+
+ uv__io_start(handle->loop, &handle->write_watcher);
+
+ if (handle->delayed_error)
+ uv__io_feed(handle->loop, &handle->write_watcher, UV__IO_WRITE);
+
+ return 0;
+}
+
+
int uv__tcp_bind(uv_tcp_t* handle, struct sockaddr_in addr) {
return uv__bind(handle,
AF_INET,
@@ -170,33 +229,34 @@ out:
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
- int r;
+ static int single_accept = -1;
- if (tcp->delayed_error) {
- uv__set_sys_error(tcp->loop, tcp->delayed_error);
- return -1;
+ if (tcp->delayed_error)
+ return uv__set_sys_error(tcp->loop, tcp->delayed_error);
+
+ if (single_accept == -1) {
+ const char* val = getenv("UV_TCP_SINGLE_ACCEPT");
+ single_accept = (val == NULL) || (atoi(val) != 0); /* on by default */
}
- if (tcp->fd < 0) {
- if ((tcp->fd = uv__socket(AF_INET, SOCK_STREAM, 0)) == -1) {
- uv__set_sys_error(tcp->loop, errno);
- return -1;
- }
+ if (!single_accept)
+ goto no_single_accept;
- if (uv__stream_open((uv_stream_t*)tcp, tcp->fd, UV_STREAM_READABLE)) {
- close(tcp->fd);
- tcp->fd = -1;
- return -1;
- }
- }
+ tcp->idle_handle = malloc(sizeof(*tcp->idle_handle));
+ if (tcp->idle_handle == NULL)
+ return uv__set_sys_error(tcp->loop, ENOMEM);
+
+ if (uv_idle_init(tcp->loop, tcp->idle_handle))
+ abort();
- assert(tcp->fd >= 0);
+ tcp->flags |= UV_TCP_SINGLE_ACCEPT;
- r = listen(tcp->fd, backlog);
- if (r < 0) {
- uv__set_sys_error(tcp->loop, errno);
+no_single_accept:
+ if (maybe_new_socket(tcp, AF_INET, UV_STREAM_READABLE))
return -1;
- }
+
+ if (listen(tcp->fd, backlog))
+ return uv__set_sys_error(tcp->loop, errno);
tcp->connection_cb = cb;
@@ -209,37 +269,31 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
int uv__tcp_connect(uv_connect_t* req,
- uv_tcp_t* handle,
- struct sockaddr_in address,
- uv_connect_cb cb) {
- int saved_errno = errno;
+ uv_tcp_t* handle,
+ struct sockaddr_in addr,
+ uv_connect_cb cb) {
+ int saved_errno;
int status;
- status = uv__connect(req,
- (uv_stream_t*)handle,
- (struct sockaddr*)&address,
- sizeof address,
- cb);
-
+ saved_errno = errno;
+ status = uv__connect(req, handle, (struct sockaddr*)&addr, sizeof addr, cb);
errno = saved_errno;
+
return status;
}
int uv__tcp_connect6(uv_connect_t* req,
- uv_tcp_t* handle,
- struct sockaddr_in6 address,
- uv_connect_cb cb) {
- int saved_errno = errno;
+ uv_tcp_t* handle,
+ struct sockaddr_in6 addr,
+ uv_connect_cb cb) {
+ int saved_errno;
int status;
- status = uv__connect(req,
- (uv_stream_t*)handle,
- (struct sockaddr*)&address,
- sizeof address,
- cb);
-
+ saved_errno = errno;
+ status = uv__connect(req, handle, (struct sockaddr*)&addr, sizeof addr, cb);
errno = saved_errno;
+
return status;
}
@@ -324,5 +378,17 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {
int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
+ if (enable)
+ handle->flags |= UV_TCP_SINGLE_ACCEPT;
+ else
+ handle->flags &= ~UV_TCP_SINGLE_ACCEPT;
return 0;
}
+
+
+void uv__tcp_close(uv_tcp_t* handle) {
+ if (handle->idle_handle)
+ uv_close((uv_handle_t*)handle->idle_handle, (uv_close_cb)free);
+
+ uv__stream_close((uv_stream_t*)handle);
+}
diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c
index 5a17bcb36..67c787698 100644
--- a/deps/uv/src/unix/thread.c
+++ b/deps/uv/src/unix/thread.c
@@ -167,6 +167,44 @@ void uv_once(uv_once_t* guard, void (*callback)(void)) {
abort();
}
+#if defined(__APPLE__) && defined(__MACH__)
+
+int uv_sem_init(uv_sem_t* sem, unsigned int value) {
+ return semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, value);
+}
+
+
+void uv_sem_destroy(uv_sem_t* sem) {
+ if (semaphore_destroy(mach_task_self(), *sem))
+ abort();
+}
+
+
+void uv_sem_post(uv_sem_t* sem) {
+ if (semaphore_signal(*sem))
+ abort();
+}
+
+
+void uv_sem_wait(uv_sem_t* sem) {
+ if (semaphore_wait(*sem))
+ abort();
+}
+
+
+int uv_sem_trywait(uv_sem_t* sem) {
+ mach_timespec_t interval;
+
+ interval.tv_sec = 0;
+ interval.tv_nsec = 0;
+
+ if (semaphore_timedwait(*sem, interval) == KERN_SUCCESS)
+ return 0;
+ else
+ return -1;
+}
+
+#else /* !(defined(__APPLE__) && defined(__MACH__)) */
int uv_sem_init(uv_sem_t* sem, unsigned int value) {
return sem_init(sem, 0, value);
@@ -209,3 +247,5 @@ int uv_sem_trywait(uv_sem_t* sem) {
return r;
}
+
+#endif /* defined(__APPLE__) && defined(__MACH__) */
diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c
index 9639634a1..75dfcd89c 100644
--- a/deps/uv/src/uv-common.c
+++ b/deps/uv/src/uv-common.c
@@ -28,10 +28,6 @@
#include <stdlib.h> /* malloc */
#include <string.h> /* memset */
-/* use inet_pton from c-ares if necessary */
-#include "ares_config.h"
-#include "ares/inet_net_pton.h"
-#include "ares/inet_ntop.h"
#define XX(uc, lc) case UV_##uc: return sizeof(uv_##lc##_t);
@@ -182,21 +178,21 @@ struct sockaddr_in6 uv_ip6_addr(const char* ip, int port) {
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(port);
- ares_inet_pton(AF_INET6, ip, &addr.sin6_addr);
+ uv_inet_pton(AF_INET6, ip, &addr.sin6_addr);
return addr;
}
int uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size) {
- const char* d = ares_inet_ntop(AF_INET, &src->sin_addr, dst, size);
- return d != dst;
+ uv_err_t err = uv_inet_ntop(AF_INET, &src->sin_addr, dst, size);
+ return err.code != UV_OK;
}
int uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size) {
- const char* d = ares_inet_ntop(AF_INET6, &src->sin6_addr, dst, size);
- return d != dst;
+ uv_err_t err = uv_inet_ntop(AF_INET6, &src->sin6_addr, dst, size);
+ return err.code != UV_OK;
}
diff --git a/deps/uv/src/win/error.c b/deps/uv/src/win/error.c
index 6490547dc..91f5111ed 100644
--- a/deps/uv/src/win/error.c
+++ b/deps/uv/src/win/error.c
@@ -86,6 +86,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
case ERROR_INVALID_REPARSE_DATA: return UV_ENOENT;
case ERROR_MOD_NOT_FOUND: return UV_ENOENT;
case ERROR_PATH_NOT_FOUND: return UV_ENOENT;
+ case WSANO_DATA: return UV_ENOENT;
case ERROR_ACCESS_DENIED: return UV_EPERM;
case ERROR_PRIVILEGE_NOT_HELD: return UV_EPERM;
case ERROR_NOACCESS: return UV_EACCES;
diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c
index 77a1c7b75..5da14eaa9 100644
--- a/deps/uv/src/win/pipe.c
+++ b/deps/uv/src/win/pipe.c
@@ -300,7 +300,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
/* Already closing. Cancel the shutdown. */
if (req->cb) {
- uv__set_sys_error(loop, WSAEINTR);
+ uv__set_artificial_error(loop, UV_ECANCELED);
req->cb(req, -1);
}
diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c
index e13c0f3df..2a25358d4 100644
--- a/deps/uv/src/win/tcp.c
+++ b/deps/uv/src/win/tcp.c
@@ -157,7 +157,6 @@ int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) {
void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
int status;
- int sys_error;
unsigned int i;
uv_tcp_accept_t* req;
@@ -169,19 +168,16 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
if (handle->flags & UV_HANDLE_CLOSING) {
status = -1;
- sys_error = WSAEINTR;
+ uv__set_artificial_error(loop, UV_ECANCELED);
} else if (shutdown(handle->socket, SD_SEND) != SOCKET_ERROR) {
status = 0;
handle->flags |= UV_HANDLE_SHUT;
} else {
status = -1;
- sys_error = WSAGetLastError();
+ uv__set_sys_error(loop, WSAGetLastError());
}
if (handle->shutdown_req->cb) {
- if (status == -1) {
- uv__set_sys_error(loop, sys_error);
- }
handle->shutdown_req->cb(handle->shutdown_req, status);
}
diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c
index 340bcdcb3..66103e6b6 100644
--- a/deps/uv/src/win/tty.c
+++ b/deps/uv/src/win/tty.c
@@ -1751,7 +1751,7 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
/* TTY shutdown is really just a no-op */
if (handle->shutdown_req->cb) {
if (handle->flags & UV_HANDLE_CLOSING) {
- uv__set_sys_error(loop, WSAEINTR);
+ uv__set_artificial_error(loop, UV_ECANCELED);
handle->shutdown_req->cb(handle->shutdown_req, -1);
} else {
handle->shutdown_req->cb(handle->shutdown_req, 0);
diff --git a/deps/uv/test/benchmark-udp-packet-storm.c b/deps/uv/test/benchmark-udp-packet-storm.c
index 594128705..9842e4cea 100644
--- a/deps/uv/test/benchmark-udp-packet-storm.c
+++ b/deps/uv/test/benchmark-udp-packet-storm.c
@@ -91,7 +91,7 @@ static void recv_cb(uv_udp_t* handle,
return;
if (nread == -1) {
- ASSERT(uv_last_error(loop).code == UV_EINTR); /* FIXME change error code */
+ ASSERT(uv_last_error(loop).code == UV_ECANCELED);
return;
}
diff --git a/deps/uv/test/test-hrtime.c b/deps/uv/test/test-hrtime.c
index 2a9156ecf..72a4d4b18 100644
--- a/deps/uv/test/test-hrtime.c
+++ b/deps/uv/test/test-hrtime.c
@@ -47,7 +47,7 @@ TEST_IMPL(hrtime) {
/* Check that the difference between the two hrtime values is somewhat in */
/* the range we expect it to be. */
ASSERT(diff > (uint64_t) 25 * NANOSEC / MILLISEC);
- ASSERT(diff < (uint64_t) 60 * NANOSEC / MILLISEC);
+ ASSERT(diff < (uint64_t) 80 * NANOSEC / MILLISEC);
--i;
}
return 0;
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
index 75e8f2ec1..19670e568 100644
--- a/deps/uv/test/test-list.h
+++ b/deps/uv/test/test-list.h
@@ -56,6 +56,7 @@ TEST_DECLARE (tcp_close)
TEST_DECLARE (tcp_flags)
TEST_DECLARE (tcp_write_error)
TEST_DECLARE (tcp_write_to_half_open_connection)
+TEST_DECLARE (tcp_unexpected_read)
TEST_DECLARE (tcp_bind6_error_addrinuse)
TEST_DECLARE (tcp_bind6_error_addrnotavail)
TEST_DECLARE (tcp_bind6_error_fault)
@@ -252,6 +253,7 @@ TASK_LIST_START
TEST_ENTRY (tcp_flags)
TEST_ENTRY (tcp_write_error)
TEST_ENTRY (tcp_write_to_half_open_connection)
+ TEST_ENTRY (tcp_unexpected_read)
TEST_ENTRY (tcp_bind6_error_addrinuse)
TEST_ENTRY (tcp_bind6_error_addrnotavail)
diff --git a/deps/uv/test/test-process-title.c b/deps/uv/test/test-process-title.c
index 59fceda31..13d9dddfc 100644
--- a/deps/uv/test/test-process-title.c
+++ b/deps/uv/test/test-process-title.c
@@ -23,20 +23,27 @@
#include "task.h"
#include <string.h>
-TEST_IMPL(process_title) {
+
+static void set_title(const char* title) {
char buffer[512];
uv_err_t err;
err = uv_get_process_title(buffer, sizeof(buffer));
ASSERT(UV_OK == err.code);
- err = uv_set_process_title("new title");
+ err = uv_set_process_title(title);
ASSERT(UV_OK == err.code);
err = uv_get_process_title(buffer, sizeof(buffer));
ASSERT(UV_OK == err.code);
- ASSERT(strcmp(buffer, "new title") == 0);
+ ASSERT(strcmp(buffer, title) == 0);
+}
+
+TEST_IMPL(process_title) {
+ /* Check for format string vulnerabilities. */
+ set_title("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s");
+ set_title("new title");
return 0;
}
diff --git a/deps/uv/test/test-shutdown-close.c b/deps/uv/test/test-shutdown-close.c
index eabbefc60..6ce46b245 100644
--- a/deps/uv/test/test-shutdown-close.c
+++ b/deps/uv/test/test-shutdown-close.c
@@ -37,9 +37,9 @@ static int close_cb_called = 0;
static void shutdown_cb(uv_shutdown_t* req, int status) {
+ int err = uv_last_error(uv_default_loop()).code;
ASSERT(req == &shutdown_req);
- ASSERT(status == 0 ||
- (status == -1 && uv_last_error(uv_default_loop()).code == UV_EINTR));
+ ASSERT(status == 0 || (status == -1 && err == UV_ECANCELED));
shutdown_cb_called++;
}
diff --git a/deps/uv/test/test-tcp-close-while-connecting.c b/deps/uv/test/test-tcp-close-while-connecting.c
index 93e331d6d..90471ecac 100644
--- a/deps/uv/test/test-tcp-close-while-connecting.c
+++ b/deps/uv/test/test-tcp-close-while-connecting.c
@@ -38,7 +38,7 @@ static void close_cb(uv_handle_t* handle) {
static void connect_cb(uv_connect_t* req, int status) {
ASSERT(status == -1);
- ASSERT(uv_last_error(req->handle->loop).code == UV_EINTR);
+ ASSERT(uv_last_error(req->handle->loop).code == UV_ECANCELED);
uv_timer_stop(&timer2_handle);
connect_cb_called++;
}
diff --git a/deps/uv/test/test-tcp-unexpected-read.c b/deps/uv/test/test-tcp-unexpected-read.c
index 7adb4dae2..45559c013 100644
--- a/deps/uv/test/test-tcp-unexpected-read.c
+++ b/deps/uv/test/test-tcp-unexpected-read.c
@@ -49,6 +49,8 @@ static void timer_cb(uv_timer_t* handle, int status) {
static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size) {
ASSERT(0 && "alloc_cb should not have been called");
+ /* Satisfy the compiler. */
+ return uv_buf_init(NULL, 0);
}
diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp
index c14df2cc0..d6a97541c 100644
--- a/deps/uv/uv.gyp
+++ b/deps/uv/uv.gyp
@@ -52,6 +52,7 @@
'include/uv-private/tree.h',
'src/cares.c',
'src/fs-poll.c',
+ 'src/inet.c',
'src/uv-common.c',
'src/uv-common.h',
'src/ares/ares_cancel.c',
@@ -358,6 +359,7 @@
'test/test-tcp-write-error.c',
'test/test-tcp-write-to-half-open-connection.c',
'test/test-tcp-writealot.c',
+ 'test/test-tcp-unexpected-read.c',
'test/test-threadpool.c',
'test/test-mutexes.c',
'test/test-thread.c',