From e0a603a4993e995080a8926fcddbbde752a2136e Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Tue, 7 Aug 2012 01:25:06 +0200 Subject: [PATCH] uv: upgrade to 3a8bb3b --- deps/uv/LICENSE | 4 + deps/uv/README.md | 6 +- deps/uv/config-mingw.mk | 8 +- deps/uv/config-unix.mk | 2 +- deps/uv/include/uv-private/uv-unix.h | 18 +- deps/uv/include/uv.h | 20 +- deps/uv/src/inet.c | 293 +++++++++++++++++++++++++ deps/uv/src/unix/core.c | 7 +- deps/uv/src/unix/freebsd.c | 18 +- deps/uv/src/unix/internal.h | 6 +- deps/uv/src/unix/pipe.c | 35 ++- deps/uv/src/unix/stream.c | 114 ++++------ deps/uv/src/unix/sunos.c | 19 +- deps/uv/src/unix/tcp.c | 180 ++++++++++----- deps/uv/src/unix/thread.c | 40 ++++ deps/uv/src/uv-common.c | 14 +- deps/uv/src/win/error.c | 1 + deps/uv/src/win/pipe.c | 2 +- deps/uv/src/win/tcp.c | 8 +- deps/uv/src/win/tty.c | 2 +- deps/uv/test/benchmark-udp-packet-storm.c | 2 +- deps/uv/test/test-hrtime.c | 2 +- deps/uv/test/test-list.h | 2 + deps/uv/test/test-process-title.c | 13 +- deps/uv/test/test-shutdown-close.c | 4 +- deps/uv/test/test-tcp-close-while-connecting.c | 2 +- deps/uv/test/test-tcp-unexpected-read.c | 2 + deps/uv/uv.gyp | 2 + 28 files changed, 630 insertions(+), 196 deletions(-) create mode 100644 deps/uv/src/inet.c diff --git a/deps/uv/LICENSE b/deps/uv/LICENSE index f62d7f1..57279fc 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 f86a000..1359742 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) + — API documentation in the form of detailed header comments. + * [An Introduction to libuv](http://nikhilm.github.com/uvbook/) — An + overview of libuv with tutorials. ## Build Instructions diff --git a/deps/uv/config-mingw.mk b/deps/uv/config-mingw.mk index 9e49ec7..8a253ba 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 0581b51..667e7b9 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 31524c0..a8dda72 100644 --- a/deps/uv/include/uv-private/uv-unix.h +++ b/deps/uv/include/uv-private/uv-unix.h @@ -40,10 +40,17 @@ #include #include -#include #include #include +#if defined(__APPLE__) && defined(__MACH__) +# include +# include +# include +#else +# include +#endif + #if __sun # include # include @@ -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 0cdc2ed..1f8beca 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 0000000..293fbf6 --- /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 +#include +#include + +#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 2f88159..4bc6b77 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 d916b0b..be8006c 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 23f16f7..233f742 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 317ac67..957e96f 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 8c33ee0..26875a7 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 a33ec9d..8c626a3 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 07ad2d9..d9cbd0b 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 #include #include #include @@ -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 5a17bcb..67c7876 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 9639634..75dfcd8 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -28,10 +28,6 @@ #include /* malloc */ #include /* 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 6490547..91f5111 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 77a1c7b..5da14ea 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 e13c0f3..2a25358 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 340bcdc..66103e6 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 5941287..9842e4c 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 2a9156e..72a4d4b 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 75e8f2e..19670e5 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 59fceda..13d9ddd 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 -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 eabbefc..6ce46b2 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 93e331d..90471ec 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 7adb4da..45559c0 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 c14df2c..d6a9754 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', -- 2.7.4