From ff40253566089cd5b89c1e6efca32d3b5772dbcb Mon Sep 17 00:00:00 2001 From: Igor Zinkovsky Date: Mon, 30 Jan 2012 15:57:08 -0800 Subject: [PATCH] upgrade uv to 812e410772 --- deps/uv/include/uv-private/uv-unix.h | 3 +++ deps/uv/include/uv-private/uv-win.h | 5 ++++ deps/uv/include/uv.h | 23 +++++++++++++++++ deps/uv/src/unix/core.c | 18 ++++++++++++++ deps/uv/src/unix/error.c | 4 +-- deps/uv/src/unix/internal.h | 24 ++++++++++++------ deps/uv/src/unix/kqueue.c | 4 +-- deps/uv/src/unix/linux.c | 3 +-- deps/uv/src/unix/stream.c | 37 ++++++++++++++++++++++++++++ deps/uv/src/unix/sunos.c | 2 +- deps/uv/src/win/internal.h | 5 +++- deps/uv/src/win/pipe.c | 2 +- deps/uv/src/win/stream.c | 24 ++++++++++++++++++ deps/uv/src/win/tcp.c | 25 +++++++++++++++++-- deps/uv/test/test-list.h | 4 +++ deps/uv/uv.gyp | 1 + 16 files changed, 165 insertions(+), 19 deletions(-) diff --git a/deps/uv/include/uv-private/uv-unix.h b/deps/uv/include/uv-private/uv-unix.h index 24ef37cb9d..792ca84a2c 100644 --- a/deps/uv/include/uv-private/uv-unix.h +++ b/deps/uv/include/uv-private/uv-unix.h @@ -192,6 +192,9 @@ typedef void* uv_lib_t; struct termios orig_termios; \ int mode; +#define UV_STREAM_INFO_PRIVATE_FIELDS \ + int fd; + /* UV_FS_EVENT_PRIVATE_FIELDS */ #if defined(__linux__) diff --git a/deps/uv/include/uv-private/uv-win.h b/deps/uv/include/uv-private/uv-win.h index 5a6a949e53..626eb6db4c 100644 --- a/deps/uv/include/uv-private/uv-win.h +++ b/deps/uv/include/uv-private/uv-win.h @@ -450,6 +450,11 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); wchar_t* dirw; \ char* buffer; +#define UV_STREAM_INFO_PRIVATE_FIELDS \ + union { \ + WSAPROTOCOL_INFOW socket_info; \ + }; + int uv_utf16_to_utf8(const wchar_t* utf16Buffer, size_t utf16Size, char* utf8Buffer, size_t utf8Size); int uv_utf8_to_utf16(const char* utf8Buffer, wchar_t* utf16Buffer, diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index cedf529375..0fbd4d6876 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -180,6 +180,7 @@ typedef struct uv_process_s uv_process_t; typedef struct uv_counters_s uv_counters_t; typedef struct uv_cpu_info_s uv_cpu_info_t; typedef struct uv_interface_address_s uv_interface_address_t; +typedef struct uv_stream_info_s uv_stream_info_t; /* Request types */ typedef struct uv_req_s uv_req_t; typedef struct uv_shutdown_s uv_shutdown_t; @@ -530,6 +531,28 @@ UV_EXTERN int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name, UV_EXTERN int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name, int* namelen); +/* + * uv_stream_info_t is used to store exported stream (using uv_export), + * which can be imported into a different event-loop within the same process + * (using uv_import). + */ +struct uv_stream_info_s { + uv_handle_type type; + UV_STREAM_INFO_PRIVATE_FIELDS +}; + +/* + * Exports uv_stream_t as uv_stream_info_t value, which could + * be used to initialize shared streams within the same process. + */ +UV_EXTERN int uv_export(uv_stream_t* stream, uv_stream_info_t* info); + +/* + * Imports uv_stream_info_t value into uv_stream_t to initialize + * shared stream. + */ +UV_EXTERN int uv_import(uv_stream_t* stream, uv_stream_info_t* info); + /* * uv_tcp_connect, uv_tcp_connect6 * These functions establish IPv4 and IPv6 TCP connections. Provide an diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 366e94b3c6..af39fc80dd 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -825,6 +825,24 @@ int uv__cloexec(int fd, int set) { } +/* This function is not execve-safe, there is a race window + * between the call to dup() and fcntl(FD_CLOEXEC). + */ +int uv__dup(int fd) { + fd = dup(fd); + + if (fd == -1) + return -1; + + if (uv__cloexec(fd, 1)) { + SAVE_ERRNO(uv__close(fd)); + return -1; + } + + return fd; +} + + /* TODO move to uv-common.c? */ size_t uv__strlcpy(char* dst, const char* src, size_t size) { const char *org; diff --git a/deps/uv/src/unix/error.c b/deps/uv/src/unix/error.c index 80d3270db0..3d9c4072e6 100644 --- a/deps/uv/src/unix/error.c +++ b/deps/uv/src/unix/error.c @@ -86,7 +86,5 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case ETIMEDOUT: return UV_ETIMEDOUT; default: return UV_UNKNOWN; } - - assert(0 && "unreachable"); - return -1; + UNREACHABLE(); } diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index a962073c19..3591090d7a 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -25,6 +25,8 @@ #include "uv-common.h" #include "uv-eio.h" +#include +#include /* abort */ #include /* offsetof */ #if __STRICT_ANSI__ @@ -133,13 +135,20 @@ inline static int sys_accept4(int fd, #define container_of(ptr, type, member) \ ((type *) ((char *) (ptr) - offsetof(type, member))) -#define SAVE_ERRNO(block) \ - do { \ - int _saved_errno = errno; \ - do { block; } while (0); \ - errno = _saved_errno; \ - } \ - while (0); +#define UNREACHABLE() \ + do { \ + assert(0 && "unreachable code"); \ + abort(); \ + } \ + while (0) + +#define SAVE_ERRNO(block) \ + do { \ + int _saved_errno = errno; \ + do { block; } while (0); \ + errno = _saved_errno; \ + } \ + while (0) /* flags */ enum { @@ -159,6 +168,7 @@ void uv__handle_init(uv_loop_t* loop, uv_handle_t* handle, uv_handle_type type); int uv__nonblock(int fd, int set) __attribute__((unused)); int uv__cloexec(int fd, int set) __attribute__((unused)); int uv__socket(int domain, int type, int protocol); +int uv__dup(int fd); /* We used to handle EINTR in uv__close() but linux 2.6 will have closed the * file descriptor anyway, even on EINTR. Retrying in that case isn't merely diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c index cea583355b..68d064dad9 100644 --- a/deps/uv/src/unix/kqueue.c +++ b/deps/uv/src/unix/kqueue.c @@ -141,13 +141,13 @@ int uv_fs_event_init(uv_loop_t* loop, void uv__fs_event_destroy(uv_fs_event_t* handle) { - assert(0 && "unreachable"); + UNREACHABLE(); } /* Called by libev, don't touch. */ void uv__kqueue_hack(EV_P_ int fflags, ev_io *w) { - assert(0 && "unreachable"); + UNREACHABLE(); } #endif /* HAVE_KQUEUE */ diff --git a/deps/uv/src/unix/linux.c b/deps/uv/src/unix/linux.c index 12473596eb..2f04cb8df9 100644 --- a/deps/uv/src/unix/linux.c +++ b/deps/uv/src/unix/linux.c @@ -679,8 +679,7 @@ int uv_fs_event_init(uv_loop_t* loop, void uv__fs_event_destroy(uv_fs_event_t* handle) { - assert(0 && "unreachable"); - abort(); + UNREACHABLE(); } #endif /* HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 */ diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index e0689fbcdc..9e58fc5377 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -966,3 +966,40 @@ int uv_read_stop(uv_stream_t* stream) { } +int uv_export(uv_stream_t* stream, uv_stream_info_t* info) { + int fd; + + if (stream->type != UV_TCP) { + uv__set_artificial_error(stream->loop, UV_EINVAL); + return -1; + } + + fd = uv__dup(stream->fd); + + if (fd == -1) { + uv__set_sys_error(stream->loop, errno); + return -1; + } + + info->type = stream->type; + info->fd = fd; + + return 0; +} + + +int uv_import(uv_stream_t* stream, uv_stream_info_t* info) { + if (info->type != UV_TCP) { + uv__set_artificial_error(stream->loop, UV_EINVAL); + return -1; + } + + if (stream->fd != -1) { + uv__set_artificial_error(stream->loop, UV_EALREADY); + return -1; + } + + stream->fd = info->fd; + + return 0; +} diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c index 49d372b495..a87a2343a8 100644 --- a/deps/uv/src/unix/sunos.c +++ b/deps/uv/src/unix/sunos.c @@ -214,7 +214,7 @@ int uv_fs_event_init(uv_loop_t* loop, void uv__fs_event_destroy(uv_fs_event_t* handle) { - assert(0 && "unreachable"); /* should never be called */ + UNREACHABLE(); } #endif /* HAVE_PORTS_FS */ diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h index 0dc551dbaa..9435bb28bd 100644 --- a/deps/uv/src/win/internal.h +++ b/deps/uv/src/win/internal.h @@ -143,11 +143,14 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle); -int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info); +int uv__tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info); int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid, LPWSAPROTOCOL_INFOW protocol_info); +int uv_tcp_export(uv_tcp_t* tcp, uv_stream_info_t* info); +int uv_tcp_import(uv_tcp_t* tcp, uv_stream_info_t* info); + /* * UDP diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index 5c20fe4801..60f137e974 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -649,7 +649,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { return -1; } - return uv_tcp_import((uv_tcp_t*)client, server->pending_socket_info); + return uv__tcp_import((uv_tcp_t*)client, server->pending_socket_info); } else { pipe_client = (uv_pipe_t*)client; diff --git a/deps/uv/src/win/stream.c b/deps/uv/src/win/stream.c index c2354eecba..7faa0a2b61 100644 --- a/deps/uv/src/win/stream.c +++ b/deps/uv/src/win/stream.c @@ -186,3 +186,27 @@ size_t uv_count_bufs(uv_buf_t bufs[], int count) { return bytes; } + + +int uv_export(uv_stream_t* stream, uv_stream_info_t* info) { + switch (stream->type) { + case UV_TCP: + return uv_tcp_export((uv_tcp_t*)stream, info); + default: + assert(0); + uv__set_sys_error(stream->loop, WSAEINVAL); + return -1; + } +} + + +int uv_import(uv_stream_t* stream, uv_stream_info_t* info) { + switch (stream->type) { + case UV_TCP: + return uv_tcp_import((uv_tcp_t*)stream, info); + default: + assert(0); + uv__set_sys_error(stream->loop, WSAEINVAL); + return -1; + } +} \ No newline at end of file diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index f810913f30..590d0792fb 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -1019,7 +1019,7 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, } -int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info) { +int uv__tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info) { SOCKET socket = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_IP, @@ -1140,4 +1140,25 @@ int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) { } return 0; -} \ No newline at end of file +} + + +int uv_tcp_export(uv_tcp_t* tcp, uv_stream_info_t* info) { + if (uv_tcp_duplicate_socket(tcp, GetCurrentProcessId(), + &info->socket_info) == -1) { + return -1; + } + + info->type = UV_TCP; + return 0; +} + + +int uv_tcp_import(uv_tcp_t* tcp, uv_stream_info_t* info) { + if (info->type != UV_TCP) { + uv__set_sys_error(tcp->loop, WSAEINVAL); + return -1; + } + + return uv__tcp_import(tcp, &info->socket_info); +} diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 31dcb0a64c..bc13dd0fe9 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -24,6 +24,8 @@ TEST_DECLARE (tty) TEST_DECLARE (stdio_over_pipes) TEST_DECLARE (ipc_listen_before_write) TEST_DECLARE (ipc_listen_after_write) +TEST_DECLARE (ipc_threads_listen_after_write) +TEST_DECLARE (ipc_threads_listen_before_write) TEST_DECLARE (tcp_ping_pong) TEST_DECLARE (tcp_ping_pong_v6) TEST_DECLARE (pipe_ping_pong) @@ -161,6 +163,8 @@ TASK_LIST_START TEST_ENTRY (stdio_over_pipes) TEST_ENTRY (ipc_listen_before_write) TEST_ENTRY (ipc_listen_after_write) + TEST_ENTRY (ipc_threads_listen_after_write) + TEST_ENTRY (ipc_threads_listen_before_write) TEST_ENTRY (tcp_ping_pong) TEST_HELPER (tcp_ping_pong, tcp4_echo_server) diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 7a88cfa1ab..3ed08433e6 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -301,6 +301,7 @@ 'test/test-hrtime.c', 'test/test-idle.c', 'test/test-ipc.c', + 'test/test-ipc-threads.c', 'test/test-list.h', 'test/test-loop-handles.c', 'test/test-multiple-listen.c',