diff --git a/deps/uv/.mailmap b/deps/uv/.mailmap index 7d627a3da3..533e10197b 100644 --- a/deps/uv/.mailmap +++ b/deps/uv/.mailmap @@ -10,10 +10,11 @@ Fedor Indutny Frank Denis Isaac Z. Schlueter Justin Venus -Keno Fischer Keno Fischer +Keno Fischer Maciej Małecki Marc Schlaich +Rasmus Christian Pedersen Rasmus Pedersen Robert Mustacchi Ryan Dahl diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index d96ec14cda..cb47cee01d 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -81,7 +81,6 @@ Marc Schlaich Brian Mazza Elliot Saba Ben Kelly -Kristian Evensen Nils Maier Nicholas Vavilov Miroslav Bajtoš @@ -111,7 +110,6 @@ Yazhong Liu Sam Roberts River Tarnell Nathan Sweet -Alex Crichton Luca Bruno Trevor Norris Oguz Bastemur @@ -119,40 +117,16 @@ Dylan Cali Austin Foxley Benjamin Saunders Geoffry Song -Rasmus Pedersen +Rasmus Christian Pedersen William Light Oleg Efimov Lars Gierth -rcp -Alexis Campailla +Rasmus Christian Pedersen Justin Venus -Ben Kelly Kristian Evensen -Sean Silva Linus Mårtensson Navaneeth Kedaram Nambiathan -Brent Cook -Brian Kaisner -Reini Urban -Maks Naumov -Sean Farrell -Christoph Iserlohn -Steven Kabbes -Tenor Biel -Andrej Manduch -Joshua Neuheisel Yorkie -Sam Roberts -River Tarnell -Nathan Sweet -Dylan Cali -Austin Foxley -Geoffry Song -Benjamin Saunders -Rasmus Pedersen -William Light -Oleg Efimov -Lars Gierth StarWing thierry-FreeBSD Isaiah Norton @@ -161,3 +135,7 @@ David Capello Paul Tan Javier Hernández Tonis Tiigi +Norio Kobota +李港平 +Chernyshev Viacheslav +Stephen von Takach diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index ea9a936d67..907af36744 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,4 +1,42 @@ -2014.04.07, Version 0.11.23 (Unstable) +2014.05.02, Version 0.11.25 (Unstable) + +Changes since version 0.11.24: + +* osx: pass const handle pointer to uv___stream_fd (Chernyshev Viacheslav) + +* unix, windows: pass const handle ptr to uv_tcp_get*name (Chernyshev + Viacheslav) + +* common: pass const sockaddr ptr to uv_ip*_name (Chernyshev Viacheslav) + +* unix, windows: validate flags on uv_udp|tcp_bind (Saúl Ibarra Corretgé) + +* unix: handle case when addr is not initialized after recvmsg (Saúl Ibarra + Corretgé) + +* unix, windows: uv_now constness (Rasmus Pedersen) + + +2014.04.15, Version 0.11.24 (Unstable), ed948c29f6e8c290f79325a6f0bc9ef35bcde644 + +Changes since version 0.11.23: + +* linux: reduce file descriptor count of async pipe (Ben Noordhuis) + +* sunos: support IPv6 qualified link-local addresses (Saúl Ibarra Corretgé) + +* windows: fix opening of read-only stdin pipes (Alexis Campailla) + +* windows: Fix an infinite loop in uv_spawn (Alex Crichton) + +* windows: fix console signal handler refcount (李港平) + +* inet: allow scopeid in uv_inet_pton (Fedor Indutny) + +* win: always leave crit section in get_proc_title (Fedor Indutny) + + +2014.04.07, Version 0.11.23 (Unstable), e54de537efcacd593f36fcaaf8b4cb9e64313275 Changes since version 0.11.22: diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index 127e0b9712..078c717eb7 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,9 +13,10 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [0.11.23], [https://github.com/joyent/libuv/issues]) +AC_INIT([libuv], [0.11.25], [https://github.com/joyent/libuv/issues]) AC_CONFIG_MACRO_DIR([m4]) m4_include([m4/libuv-extra-automake-flags.m4]) +m4_include([m4/as_case.m4]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects] UV_EXTRA_AUTOMAKE_FLAGS) AC_CANONICAL_HOST AC_ENABLE_SHARED diff --git a/deps/uv/include/uv-sunos.h b/deps/uv/include/uv-sunos.h index 042166424e..c4cd83ddb1 100644 --- a/deps/uv/include/uv-sunos.h +++ b/deps/uv/include/uv-sunos.h @@ -41,4 +41,6 @@ #endif /* defined(PORT_SOURCE_FILE) */ +#define UV_PLATFORM_HAS_IP6_LINK_LOCAL_ADDRESS + #endif /* UV_SUNOS_H */ diff --git a/deps/uv/include/uv-unix.h b/deps/uv/include/uv-unix.h index b1509058a3..40c49894c5 100644 --- a/deps/uv/include/uv-unix.h +++ b/deps/uv/include/uv-unix.h @@ -218,8 +218,8 @@ typedef struct { uv_buf_t bufsml[4]; \ #define UV_HANDLE_PRIVATE_FIELDS \ - int flags; \ uv_handle_t* next_closing; \ + unsigned int flags; \ #define UV_STREAM_PRIVATE_FIELDS \ uv_connect_t *connect_req; \ diff --git a/deps/uv/include/uv-version.h b/deps/uv/include/uv-version.h index 5724ee0887..bd69f6c94d 100644 --- a/deps/uv/include/uv-version.h +++ b/deps/uv/include/uv-version.h @@ -32,7 +32,7 @@ #define UV_VERSION_MAJOR 0 #define UV_VERSION_MINOR 11 -#define UV_VERSION_PATCH 23 +#define UV_VERSION_PATCH 25 #define UV_VERSION_IS_RELEASE 1 #endif /* UV_VERSION_H */ diff --git a/deps/uv/include/uv-win.h b/deps/uv/include/uv-win.h index c254280102..211c593835 100644 --- a/deps/uv/include/uv-win.h +++ b/deps/uv/include/uv-win.h @@ -428,7 +428,8 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); void* queue[2]; \ int queue_len; \ } pending_ipc_info; \ - uv_write_t* non_overlapped_writes_tail; + uv_write_t* non_overlapped_writes_tail; \ + void* reserved; #define UV_PIPE_PRIVATE_FIELDS \ HANDLE handle; \ diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 7eb4d5fd2c..d4566268b9 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -345,7 +345,7 @@ UV_EXTERN void uv_update_time(uv_loop_t*); * * Use uv_hrtime() if you need sub-millisecond granularity. */ -UV_EXTERN uint64_t uv_now(uv_loop_t*); +UV_EXTERN uint64_t uv_now(const uv_loop_t*); /* * Get backend file descriptor. Only kqueue, epoll and event ports are @@ -695,9 +695,8 @@ UV_EXTERN int uv_write2(uv_write_t* req, * Same as `uv_write()`, but won't queue write request if it can't be completed * immediately. * Will return either: - * - positive number of bytes written - * - zero - if queued write is needed - * - negative error code + * - >= 0: number of bytes written (can be less than the supplied buffer size) + * - < 0: negative error code */ UV_EXTERN int uv_try_write(uv_stream_t* handle, const uv_buf_t bufs[], @@ -809,10 +808,12 @@ enum uv_tcp_flags { UV_EXTERN int uv_tcp_bind(uv_tcp_t* handle, const struct sockaddr* addr, unsigned int flags); -UV_EXTERN int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name, - int* namelen); -UV_EXTERN int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name, - int* namelen); +UV_EXTERN int uv_tcp_getsockname(const uv_tcp_t* handle, + struct sockaddr* name, + int* namelen); +UV_EXTERN int uv_tcp_getpeername(const uv_tcp_t* handle, + struct sockaddr* name, + int* namelen); /* * Establish an IPv4 or IPv6 TCP connection. Provide an initialized TCP handle @@ -873,8 +874,8 @@ typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status); * discard or repurpose the read buffer. * < 0 if a transmission error was detected. * buf uv_buf_t with the received data. - * addr struct sockaddr_in or struct sockaddr_in6. - * Valid for the duration of the callback only. + * addr struct sockaddr* containing the address of the sender. + * Can be NULL. Valid for the duration of the callback only. * flags One or more OR'ed UV_UDP_* constants. * Right now only UV_UDP_PARTIAL is used. */ @@ -2055,8 +2056,8 @@ UV_EXTERN int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr); UV_EXTERN int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr); /* Convert binary addresses to strings */ -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); +UV_EXTERN int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size); +UV_EXTERN int uv_ip6_name(const 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 0. If an error */ diff --git a/deps/uv/src/inet.c b/deps/uv/src/inet.c index a30c0d1512..9220de64c6 100644 --- a/deps/uv/src/inet.c +++ b/deps/uv/src/inet.c @@ -225,7 +225,7 @@ static int inet_pton6(const char *src, unsigned char *dst) { curtok = src; seen_xdigits = 0; val = 0; - while ((ch = *src++) != '\0') { + while ((ch = *src++) != '\0' && ch != '%') { const char *pch; if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) @@ -256,7 +256,19 @@ static int inet_pton6(const char *src, unsigned char *dst) { continue; } if (ch == '.' && ((tp + sizeof(struct in_addr)) <= endp)) { - int err = inet_pton4(curtok, tp); + int err; + + /* Scope id present, parse ipv4 addr without it */ + pch = strchr(curtok, '%'); + if (pch != NULL) { + char tmp[sizeof "255.255.255.255"]; + + memcpy(tmp, curtok, pch - curtok); + curtok = tmp; + src = pch; + } + + err = inet_pton4(curtok, tp); if (err == 0) { tp += sizeof(struct in_addr); seen_xdigits = 0; diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c index 2c3bc82aef..5ef787c39d 100644 --- a/deps/uv/src/unix/async.c +++ b/deps/uv/src/unix/async.c @@ -26,6 +26,7 @@ #include "internal.h" #include +#include /* snprintf() */ #include #include #include @@ -217,8 +218,28 @@ int uv__async_start(uv_loop_t* loop, struct uv__async* wa, uv__async_cb cb) { pipefd[0] = err; pipefd[1] = -1; } - else if (err == -ENOSYS) + else if (err == -ENOSYS) { err = uv__make_pipe(pipefd, UV__F_NONBLOCK); +#if defined(__linux__) + /* Save a file descriptor by opening one of the pipe descriptors as + * read/write through the procfs. That file descriptor can then + * function as both ends of the pipe. + */ + if (err == 0) { + char buf[32]; + int fd; + + snprintf(buf, sizeof(buf), "/proc/self/fd/%d", pipefd[0]); + fd = uv__open_cloexec(buf, O_RDWR); + if (fd != -1) { + uv__close(pipefd[0]); + uv__close(pipefd[1]); + pipefd[0] = fd; + pipefd[1] = fd; + } + } +#endif + } if (err < 0) return err; @@ -236,14 +257,15 @@ void uv__async_stop(uv_loop_t* loop, struct uv__async* wa) { if (wa->io_watcher.fd == -1) return; - uv__io_stop(loop, &wa->io_watcher, UV__POLLIN); - uv__close(wa->io_watcher.fd); - wa->io_watcher.fd = -1; - if (wa->wfd != -1) { - uv__close(wa->wfd); + if (wa->wfd != wa->io_watcher.fd) + uv__close(wa->wfd); wa->wfd = -1; } + + uv__io_stop(loop, &wa->io_watcher, UV__POLLIN); + uv__close(wa->io_watcher.fd); + wa->io_watcher.fd = -1; } diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index e4ff91b887..fd29b88d42 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -241,8 +241,8 @@ void uv__udp_finish_close(uv_udp_t* handle); uv_handle_type uv__handle_type(int fd); #if defined(__APPLE__) -int uv___stream_fd(uv_stream_t* handle); -#define uv__stream_fd(handle) (uv___stream_fd((uv_stream_t*) (handle))) +int uv___stream_fd(const uv_stream_t* handle); +#define uv__stream_fd(handle) (uv___stream_fd((const uv_stream_t*) (handle))) #else #define uv__stream_fd(handle) ((handle)->io_watcher.fd) #endif /* defined(__APPLE__) */ diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index e1f660309d..ac943ec681 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -1482,8 +1482,8 @@ int uv_is_writable(const uv_stream_t* stream) { #if defined(__APPLE__) -int uv___stream_fd(uv_stream_t* handle) { - uv__stream_select_t* s; +int uv___stream_fd(const uv_stream_t* handle) { + const uv__stream_select_t* s; assert(handle->type == UV_TCP || handle->type == UV_TTY || diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c index 80b5471a7b..8c19c1ab95 100644 --- a/deps/uv/src/unix/tcp.c +++ b/deps/uv/src/unix/tcp.c @@ -63,6 +63,10 @@ int uv__tcp_bind(uv_tcp_t* tcp, int err; int on; + /* Cannot set IPv6-only mode on non-IPv6 socket. */ + if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6) + return -EINVAL; + err = maybe_new_socket(tcp, addr->sa_family, UV_STREAM_READABLE | UV_STREAM_WRITABLE); @@ -158,7 +162,7 @@ int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { } -int uv_tcp_getsockname(uv_tcp_t* handle, +int uv_tcp_getsockname(const uv_tcp_t* handle, struct sockaddr* name, int* namelen) { socklen_t socklen; @@ -180,7 +184,7 @@ int uv_tcp_getsockname(uv_tcp_t* handle, } -int uv_tcp_getpeername(uv_tcp_t* handle, +int uv_tcp_getpeername(const uv_tcp_t* handle, struct sockaddr* name, int* namelen) { socklen_t socklen; diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index efc180c78d..206c65d34f 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -221,16 +221,17 @@ static void uv__udp_recvmsg(uv_loop_t* loop, handle->recv_cb(handle, -errno, &buf, NULL, 0); } else { - flags = 0; + const struct sockaddr *addr; + if (h.msg_namelen == 0) + addr = NULL; + else + addr = (const struct sockaddr*) &peer; + flags = 0; if (h.msg_flags & MSG_TRUNC) flags |= UV_UDP_PARTIAL; - handle->recv_cb(handle, - nread, - &buf, - (const struct sockaddr*) &peer, - flags); + handle->recv_cb(handle, nread, &buf, addr, flags); } } /* recv_cb callback may decide to pause or close the handle */ diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index 2a6316a878..96f66d6d33 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -142,12 +142,12 @@ int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) { } -int uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size) { +int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) { return uv_inet_ntop(AF_INET, &src->sin_addr, dst, size); } -int uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size) { +int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) { return uv_inet_ntop(AF_INET6, &src->sin6_addr, dst, size); } @@ -384,7 +384,7 @@ void uv_stop(uv_loop_t* loop) { } -uint64_t uv_now(uv_loop_t* loop) { +uint64_t uv_now(const uv_loop_t* loop) { return loop->time; } diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index 8791604f67..394faebb60 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -223,20 +223,43 @@ int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access, } -static int uv_set_pipe_handle(uv_loop_t* loop, uv_pipe_t* handle, - HANDLE pipeHandle, DWORD duplex_flags) { +static int uv_set_pipe_handle(uv_loop_t* loop, + uv_pipe_t* handle, + HANDLE pipeHandle, + DWORD duplex_flags) { NTSTATUS nt_status; IO_STATUS_BLOCK io_status; FILE_MODE_INFORMATION mode_info; DWORD mode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT; + DWORD current_mode = 0; + DWORD err = 0; if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) { - /* If this returns ERROR_INVALID_PARAMETER we probably opened something */ - /* that is not a pipe. */ - if (GetLastError() == ERROR_INVALID_PARAMETER) { - SetLastError(WSAENOTSOCK); + err = GetLastError(); + if (err == ERROR_ACCESS_DENIED) { + /* + * SetNamedPipeHandleState can fail if the handle doesn't have either + * GENERIC_WRITE or FILE_WRITE_ATTRIBUTES. + * But if the handle already has the desired wait and blocking modes + * we can continue. + */ + if (!GetNamedPipeHandleState(pipeHandle, ¤t_mode, NULL, NULL, + NULL, NULL, 0)) { + return -1; + } else if (current_mode != mode) { + SetLastError(ERROR_ACCESS_DENIED); + return -1; + } else { + duplex_flags &= ~UV_HANDLE_WRITABLE; + } + } else { + /* If this returns ERROR_INVALID_PARAMETER we probably opened + * something that is not a pipe. */ + if (err == ERROR_INVALID_PARAMETER) { + SetLastError(WSAENOTSOCK); + } + return -1; } - return -1; } /* Check if the pipe was created with FILE_FLAG_OVERLAPPED. */ @@ -1749,15 +1772,14 @@ static void eof_timer_close_cb(uv_handle_t* handle) { int uv_pipe_open(uv_pipe_t* pipe, uv_file file) { HANDLE os_handle = uv__get_osfhandle(file); + DWORD duplex_flags = UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; if (os_handle == INVALID_HANDLE_VALUE || - uv_set_pipe_handle(pipe->loop, pipe, os_handle, 0) == -1) { + uv_set_pipe_handle(pipe->loop, pipe, os_handle, duplex_flags) == -1) { return UV_EINVAL; } uv_pipe_connection_init(pipe); - pipe->handle = os_handle; - pipe->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; if (pipe->ipc) { assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)); diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c index 9d5144d748..d52c8370b6 100644 --- a/deps/uv/src/win/process.c +++ b/deps/uv/src/win/process.c @@ -378,7 +378,7 @@ static WCHAR* search_path(const WCHAR *file, } /* Skip the separator that dir_end now points to */ - if (dir_end != path) { + if (dir_end != path || *path == L';') { dir_end++; } diff --git a/deps/uv/src/win/signal.c b/deps/uv/src/win/signal.c index fc489f6193..2c64a55dc3 100644 --- a/deps/uv/src/win/signal.c +++ b/deps/uv/src/win/signal.c @@ -130,8 +130,10 @@ static int uv__signal_register_control_handler() { /* If the console control handler has already been hooked, just add a */ /* reference. */ - if (uv__signal_control_handler_refs > 0) + if (uv__signal_control_handler_refs > 0) { + uv__signal_control_handler_refs++; return 0; + } if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE)) return GetLastError(); diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index d3df3ae3a6..9d1c767d36 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -243,7 +243,13 @@ static int uv_tcp_try_bind(uv_tcp_t* handle, int r; if (handle->socket == INVALID_SOCKET) { - SOCKET sock = socket(addr->sa_family, SOCK_STREAM, 0); + SOCKET sock; + + /* Cannot set IPv6-only mode on non-IPv6 socket. */ + if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6) + return ERROR_INVALID_PARAMETER; + + sock = socket(addr->sa_family, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { return WSAGetLastError(); } @@ -747,8 +753,9 @@ static int uv_tcp_try_connect(uv_connect_t* req, } -int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name, - int* namelen) { +int uv_tcp_getsockname(const uv_tcp_t* handle, + struct sockaddr* name, + int* namelen) { int result; if (!(handle->flags & UV_HANDLE_BOUND)) { @@ -768,8 +775,9 @@ int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name, } -int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name, - int* namelen) { +int uv_tcp_getpeername(const uv_tcp_t* handle, + struct sockaddr* name, + int* namelen) { int result; if (!(handle->flags & UV_HANDLE_BOUND)) { diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index 32a82fa051..d4173c52e1 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -452,6 +452,7 @@ int uv_get_process_title(char* buffer, size_t size) { * we must query it with getConsoleTitleW */ if (!process_title && uv__get_process_title() == -1) { + LeaveCriticalSection(&process_title_lock); return uv_translate_sys_error(GetLastError()); } diff --git a/deps/uv/test/echo-server.c b/deps/uv/test/echo-server.c index e5201b9f4c..f0937ccaac 100644 --- a/deps/uv/test/echo-server.c +++ b/deps/uv/test/echo-server.c @@ -51,24 +51,20 @@ static void after_write(uv_write_t* req, int status) { /* Free the read/write buffer and the request */ wr = (write_req_t*) req; free(wr->buf.base); - free(wr); - - if (status == 0) - return; - fprintf(stderr, "uv_write error: %s\n", uv_strerror(status)); - - if (status == UV_ECANCELED) + if (status == 0) { + free(wr); return; + } - ASSERT(status == UV_EPIPE); - uv_close((uv_handle_t*)req->handle, on_close); -} - + fprintf(stderr, + "uv_write error: %s - %s\n", + uv_err_name(status), + uv_strerror(status)); -static void after_shutdown(uv_shutdown_t* req, int status) { - uv_close((uv_handle_t*)req->handle, on_close); - free(req); + if (!uv_is_closing((uv_handle_t*) req->handle)) + uv_close((uv_handle_t*) req->handle, on_close); + free(wr); } @@ -77,7 +73,6 @@ static void after_read(uv_stream_t* handle, const uv_buf_t* buf) { int i; write_req_t *wr; - uv_shutdown_t* req; if (nread < 0) { /* Error or EOF */ @@ -87,9 +82,7 @@ static void after_read(uv_stream_t* handle, free(buf->base); } - req = (uv_shutdown_t*) malloc(sizeof *req); - uv_shutdown(req, handle, after_shutdown); - + uv_close((uv_handle_t*) handle, on_close); return; } @@ -119,8 +112,9 @@ static void after_read(uv_stream_t* handle, } wr = (write_req_t*) malloc(sizeof *wr); - + ASSERT(wr != NULL); wr->buf = uv_buf_init(buf->base, nread); + if (uv_write(&wr->req, handle, &wr->buf, 1, after_write)) { FATAL("uv_write failed"); } diff --git a/deps/uv/test/test-getaddrinfo.c b/deps/uv/test/test-getaddrinfo.c index bca2a6bd70..32ca91effa 100644 --- a/deps/uv/test/test-getaddrinfo.c +++ b/deps/uv/test/test-getaddrinfo.c @@ -126,6 +126,7 @@ TEST_IMPL(getaddrinfo_concurrent) { callback_counts[i] = 0; data = (int*)malloc(sizeof(int)); + ASSERT(data != NULL); *data = i; getaddrinfo_handles[i].data = data; diff --git a/deps/uv/test/test-ip6-addr.c b/deps/uv/test/test-ip6-addr.c index ddd0812285..0d2606eee3 100644 --- a/deps/uv/test/test-ip6-addr.c +++ b/deps/uv/test/test-ip6-addr.c @@ -97,3 +97,45 @@ TEST_IMPL(ip6_addr_link_local) { RETURN_SKIP("Qualified link-local addresses are not supported."); #endif } + + +#define GOOD_ADDR_LIST(X) \ + X("::") \ + X("::1") \ + X("fe80::1") \ + X("fe80::") \ + X("fe80::2acf:daff:fedd:342a") \ + X("fe80:0:0:0:2acf:daff:fedd:342a") \ + X("fe80:0:0:0:2acf:daff:1.2.3.4") \ + +#define BAD_ADDR_LIST(X) \ + X(":::1") \ + X("abcde::1") \ + X("fe80:0:0:0:2acf:daff:fedd:342a:5678") \ + X("fe80:0:0:0:2acf:daff:abcd:1.2.3.4") \ + X("fe80:0:0:2acf:daff:1.2.3.4.5") \ + +#define TEST_GOOD(ADDR) \ + ASSERT(0 == uv_inet_pton(AF_INET6, ADDR, &addr)); \ + ASSERT(0 == uv_inet_pton(AF_INET6, ADDR "%en1", &addr)); \ + ASSERT(0 == uv_inet_pton(AF_INET6, ADDR "%%%%", &addr)); \ + ASSERT(0 == uv_inet_pton(AF_INET6, ADDR "%en1:1.2.3.4", &addr)); \ + +#define TEST_BAD(ADDR) \ + ASSERT(0 != uv_inet_pton(AF_INET6, ADDR, &addr)); \ + ASSERT(0 != uv_inet_pton(AF_INET6, ADDR "%en1", &addr)); \ + ASSERT(0 != uv_inet_pton(AF_INET6, ADDR "%%%%", &addr)); \ + ASSERT(0 != uv_inet_pton(AF_INET6, ADDR "%en1:1.2.3.4", &addr)); \ + +TEST_IMPL(ip6_pton) { + struct in6_addr addr; + + GOOD_ADDR_LIST(TEST_GOOD) + BAD_ADDR_LIST(TEST_BAD) + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +#undef GOOD_ADDR_LIST +#undef BAD_ADDR_LIST diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index f44d9f96e9..5bb8f67a54 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -41,6 +41,7 @@ TEST_DECLARE (semaphore_2) TEST_DECLARE (semaphore_3) TEST_DECLARE (tty) TEST_DECLARE (stdio_over_pipes) +TEST_DECLARE (ip6_pton) TEST_DECLARE (ipc_listen_before_write) TEST_DECLARE (ipc_listen_after_write) #ifndef _WIN32 @@ -64,6 +65,7 @@ TEST_DECLARE (tcp_bind_error_addrnotavail_2) TEST_DECLARE (tcp_bind_error_fault) TEST_DECLARE (tcp_bind_error_inval) TEST_DECLARE (tcp_bind_localhost_ok) +TEST_DECLARE (tcp_bind_invalid_flags) TEST_DECLARE (tcp_listen_without_bind) TEST_DECLARE (tcp_connect_error_fault) TEST_DECLARE (tcp_connect_timeout) @@ -244,6 +246,7 @@ TEST_DECLARE (environment_creation) TEST_DECLARE (listen_with_simultaneous_accepts) TEST_DECLARE (listen_no_simultaneous_accepts) TEST_DECLARE (fs_stat_root) +TEST_DECLARE (spawn_with_an_odd_path) #else TEST_DECLARE (emfile) TEST_DECLARE (close_fd) @@ -294,6 +297,7 @@ TASK_LIST_START TEST_ENTRY (pipe_server_close) TEST_ENTRY (tty) TEST_ENTRY (stdio_over_pipes) + TEST_ENTRY (ip6_pton) TEST_ENTRY (ipc_listen_before_write) TEST_ENTRY (ipc_listen_after_write) #ifndef _WIN32 @@ -332,6 +336,7 @@ TASK_LIST_START TEST_ENTRY (tcp_bind_error_fault) TEST_ENTRY (tcp_bind_error_inval) TEST_ENTRY (tcp_bind_localhost_ok) + TEST_ENTRY (tcp_bind_invalid_flags) TEST_ENTRY (tcp_listen_without_bind) TEST_ENTRY (tcp_connect_error_fault) TEST_ENTRY (tcp_connect_timeout) @@ -500,6 +505,7 @@ TASK_LIST_START TEST_ENTRY (listen_with_simultaneous_accepts) TEST_ENTRY (listen_no_simultaneous_accepts) TEST_ENTRY (fs_stat_root) + TEST_ENTRY (spawn_with_an_odd_path) #else TEST_ENTRY (emfile) TEST_ENTRY (close_fd) diff --git a/deps/uv/test/test-ping-pong.c b/deps/uv/test/test-ping-pong.c index c579fdd668..81941ab83d 100644 --- a/deps/uv/test/test-ping-pong.c +++ b/deps/uv/test/test-ping-pong.c @@ -155,8 +155,10 @@ static void tcp_pinger_v6_new(void) { struct sockaddr_in6 server_addr; pinger_t *pinger; + ASSERT(0 ==uv_ip6_addr("::1", TEST_PORT, &server_addr)); pinger = malloc(sizeof(*pinger)); + ASSERT(pinger != NULL); pinger->state = 0; pinger->pongs = 0; @@ -185,6 +187,7 @@ static void tcp_pinger_new(void) { ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr)); pinger = malloc(sizeof(*pinger)); + ASSERT(pinger != NULL); pinger->state = 0; pinger->pongs = 0; @@ -211,6 +214,7 @@ static void pipe_pinger_new(void) { pinger_t *pinger; pinger = (pinger_t*)malloc(sizeof(*pinger)); + ASSERT(pinger != NULL); pinger->state = 0; pinger->pongs = 0; diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index a3856d1c8e..0f4389f18c 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -171,6 +171,7 @@ TEST_IMPL(spawn_fails) { r = uv_spawn(uv_default_loop(), &process, &options); ASSERT(r == UV_ENOENT || r == UV_EACCES); ASSERT(0 == uv_is_active((uv_handle_t*) &process)); + uv_close((uv_handle_t*) &process, NULL); ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); MAKE_VALGRIND_HAPPY(); @@ -690,9 +691,9 @@ TEST_IMPL(spawn_closed_process_io) { uv_write_t write_req; uv_buf_t buf; uv_stdio_container_t stdio[2]; - static char buffer[] = "hello-from-spawn_stdin"; + static char buffer[] = "hello-from-spawn_stdin\n"; - init_process_options("spawn_helper1", exit_cb); + init_process_options("spawn_helper3", exit_cb); uv_pipe_init(uv_default_loop(), &in, 0); options.stdio = stdio; @@ -836,6 +837,7 @@ TEST_IMPL(argument_escaping) { WCHAR* non_verbatim_output; test_output = calloc(count, sizeof(WCHAR*)); + ASSERT(test_output != NULL); for (i = 0; i < count; ++i) { test_output[i] = calloc(2 * (wcslen(test_str[i]) + 2), sizeof(WCHAR)); quote_cmd_arg(test_str[i], test_output[i]); @@ -844,6 +846,7 @@ TEST_IMPL(argument_escaping) { total_size += wcslen(test_output[i]) + 1; } command_line = calloc(total_size + 1, sizeof(WCHAR)); + ASSERT(command_line != NULL); for (i = 0; i < count; ++i) { wcscat(command_line, test_output[i]); wcscat(command_line, L" "); @@ -935,6 +938,28 @@ TEST_IMPL(environment_creation) { return 0; } + +// Regression test for issue #909 +TEST_IMPL(spawn_with_an_odd_path) { + int r; + + char newpath[2048]; + char *path = getenv("PATH"); + ASSERT(path != NULL); + snprintf(newpath, 2048, ";.;%s", path); + SetEnvironmentVariable("PATH", path); + + init_process_options("", exit_cb); + options.file = options.args[0] = "program-that-had-better-not-exist"; + r = uv_spawn(uv_default_loop(), &process, &options); + ASSERT(r == UV_ENOENT || r == UV_EACCES); + ASSERT(0 == uv_is_active((uv_handle_t*) &process)); + uv_close((uv_handle_t*) &process, NULL); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + MAKE_VALGRIND_HAPPY(); + return 0; +} #endif #ifndef _WIN32 diff --git a/deps/uv/test/test-tcp-bind-error.c b/deps/uv/test/test-tcp-bind-error.c index 96bfe11601..10ed68e10e 100644 --- a/deps/uv/test/test-tcp-bind-error.c +++ b/deps/uv/test/test-tcp-bind-error.c @@ -185,6 +185,23 @@ TEST_IMPL(tcp_bind_localhost_ok) { } +TEST_IMPL(tcp_bind_invalid_flags) { + struct sockaddr_in addr; + uv_tcp_t server; + int r; + + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + + r = uv_tcp_init(uv_default_loop(), &server); + ASSERT(r == 0); + r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, UV_TCP_IPV6ONLY); + ASSERT(r == UV_EINVAL); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + TEST_IMPL(tcp_listen_without_bind) { int r; uv_tcp_t server; diff --git a/deps/uv/test/test-threadpool-cancel.c b/deps/uv/test/test-threadpool-cancel.c index 3f5164378f..a349876bd7 100644 --- a/deps/uv/test/test-threadpool-cancel.c +++ b/deps/uv/test/test-threadpool-cancel.c @@ -86,7 +86,9 @@ static void saturate_threadpool(void) { * the thread pool is saturated. As with any timing dependent test, * this is obviously not ideal. */ - if (uv_cond_timedwait(&signal_cond, &signal_mutex, (uint64_t)(350 * 1e6))) { + if (uv_cond_timedwait(&signal_cond, + &signal_mutex, + (uint64_t) (350 * 1e6))) { ASSERT(0 == uv_cancel((uv_req_t*) req)); break; } diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 5425dd63a4..710bd40bbd 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -321,6 +321,7 @@ 'test/test-getsockname.c', 'test/test-hrtime.c', 'test/test-idle.c', + 'test/test-ip6-addr.c', 'test/test-ipc.c', 'test/test-ipc-send-recv.c', 'test/test-list.h',