From b8649fdf00d0ddab8c95df2a5af80a5c3c97fca1 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Mon, 13 Feb 2012 22:37:21 +0100 Subject: [PATCH 1/4] unix: don't flush tty on switch to raw mode Drain, don't flush the tty when switching from cooked to raw mode. Prevents buffered keystrokes from getting lost. Switching back to cooked mode still flushes. Fixes joyent/node#2744. --- src/unix/tty.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/unix/tty.c b/src/unix/tty.c index 18a89216..c1429660 100644 --- a/src/unix/tty.c +++ b/src/unix/tty.c @@ -76,8 +76,8 @@ int uv_tty_set_mode(uv_tty_t* tty, int mode) { raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; - /* Put terminal in raw mode after flushing */ - if (tcsetattr(fd, TCSAFLUSH, &raw)) { + /* Put terminal in raw mode after draining */ + if (tcsetattr(fd, TCSADRAIN, &raw)) { goto fatal; } From 86ebe48660ed767dc354d59fa5213d94dd517962 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Thu, 16 Feb 2012 23:58:14 +0100 Subject: [PATCH 2/4] Windows: add error mappings that map to EPIPE --- src/win/error.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/win/error.c b/src/win/error.c index bc7cfdf0..1922f203 100644 --- a/src/win/error.c +++ b/src/win/error.c @@ -108,6 +108,9 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case ERROR_INVALID_PARAMETER: return UV_EINVAL; case ERROR_NO_UNICODE_TRANSLATION: return UV_ECHARSET; case ERROR_BROKEN_PIPE: return UV_EOF; + case ERROR_BAD_PIPE: return UV_EPIPE; + case ERROR_NO_DATA: return UV_EPIPE; + case ERROR_PIPE_NOT_CONNECTED: return UV_EPIPE; case ERROR_PIPE_BUSY: return UV_EBUSY; case ERROR_SEM_TIMEOUT: return UV_ETIMEDOUT; case WSAETIMEDOUT: return UV_ETIMEDOUT; From c0e7044862524e9b12a7f770623e7fd9763c6309 Mon Sep 17 00:00:00 2001 From: Igor Zinkovsky Date: Mon, 20 Feb 2012 21:53:43 -0800 Subject: [PATCH 3/4] windows: avoid IOCP short-circuit if non-ifs lsps are detected --- src/win/internal.h | 4 ++++ src/win/tcp.c | 10 ++++++++- src/win/winsock.c | 53 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/src/win/internal.h b/src/win/internal.h index 336349b1..7818d6b4 100644 --- a/src/win/internal.h +++ b/src/win/internal.h @@ -337,6 +337,10 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers, /* Whether ipv6 is supported */ extern int uv_allow_ipv6; +/* Whether there are any non-IFS LSPs stacked on TCP */ +extern int uv_tcp_non_ifs_lsp_ipv4; +extern int uv_tcp_non_ifs_lsp_ipv6; + /* Ip address used to bind to any port at any interface */ extern struct sockaddr_in uv_addr_ip4_any_; extern struct sockaddr_in6 uv_addr_ip6_any_; diff --git a/src/win/tcp.c b/src/win/tcp.c index 7965f73a..628d294d 100644 --- a/src/win/tcp.c +++ b/src/win/tcp.c @@ -85,6 +85,7 @@ static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsign static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle, SOCKET socket, int imported) { DWORD yes = 1; + int non_ifs_lsp; assert(handle->socket == INVALID_SOCKET); @@ -114,7 +115,10 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle, } } - if (pSetFileCompletionNotificationModes) { + non_ifs_lsp = (handle->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 : + uv_tcp_non_ifs_lsp_ipv4; + + if (pSetFileCompletionNotificationModes && !non_ifs_lsp) { if (pSetFileCompletionNotificationModes((HANDLE) socket, FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { @@ -1039,6 +1043,10 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info) { tcp->flags |= UV_HANDLE_BOUND; tcp->flags |= UV_HANDLE_SHARED_TCP_SERVER; + if (socket_protocol_info->iAddressFamily == AF_INET6) { + tcp->flags |= UV_HANDLE_IPV6; + } + return uv_tcp_set_socket(tcp->loop, tcp, socket, 1); } diff --git a/src/win/winsock.c b/src/win/winsock.c index 78acba90..667145dd 100644 --- a/src/win/winsock.c +++ b/src/win/winsock.c @@ -28,6 +28,10 @@ /* Whether ipv6 is supported */ int uv_allow_ipv6; +/* Whether there are any non-IFS LSPs stacked on TCP */ +int uv_tcp_non_ifs_lsp_ipv4; +int uv_tcp_non_ifs_lsp_ipv6; + /* Ip address used to bind to any port at any interface */ struct sockaddr_in uv_addr_ip4_any_; struct sockaddr_in6 uv_addr_ip6_any_; @@ -80,7 +84,9 @@ void uv_winsock_init() { WSADATA wsa_data; int errorno; - SOCKET dummy6; + SOCKET dummy; + WSAPROTOCOL_INFOW protocol_info; + int opt_len; /* Initialize winsock */ errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data); @@ -92,11 +98,48 @@ void uv_winsock_init() { uv_addr_ip4_any_ = uv_ip4_addr("0.0.0.0", 0); uv_addr_ip6_any_ = uv_ip6_addr("::", 0); - /* Detect IPV6 support */ - dummy6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP); - if (dummy6 != INVALID_SOCKET) { + /* Detect non-IFS LSPs */ + dummy = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + if (dummy == INVALID_SOCKET) { + uv_fatal_error(WSAGetLastError(), "socket"); + } + + opt_len = (int) sizeof protocol_info; + if (!getsockopt(dummy, + SOL_SOCKET, + SO_PROTOCOL_INFOW, + (char*) &protocol_info, + &opt_len) == SOCKET_ERROR) { + uv_fatal_error(WSAGetLastError(), "socket"); + } + + if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)) { + uv_tcp_non_ifs_lsp_ipv4 = 1; + } + + if (closesocket(dummy) == SOCKET_ERROR) { + uv_fatal_error(WSAGetLastError(), "closesocket"); + } + + /* Detect IPV6 support and non-IFS LSPs */ + dummy = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP); + if (dummy != INVALID_SOCKET) { uv_allow_ipv6 = TRUE; - if (closesocket(dummy6) == SOCKET_ERROR) { + + opt_len = (int) sizeof protocol_info; + if (!getsockopt(dummy, + SOL_SOCKET, + SO_PROTOCOL_INFOW, + (char*) &protocol_info, + &opt_len) == SOCKET_ERROR) { + uv_fatal_error(WSAGetLastError(), "socket"); + } + + if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)) { + uv_tcp_non_ifs_lsp_ipv6 = 1; + } + + if (closesocket(dummy) == SOCKET_ERROR) { uv_fatal_error(WSAGetLastError(), "closesocket"); } } From fca18c33ac94cd3893e803bf6101d0c9b2823e1a Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Thu, 23 Feb 2012 14:23:02 -0800 Subject: [PATCH 4/4] win: fs: handle EOF in read in luvit after upgrade libuv from 243cfc to d3efef readSync started failing. It seems that the code cleanup stopped handling EOF Trivially reproduced with this local fs = require('fs') print(fs.readFileSync('foo.luvit')) --- src/win/fs.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/win/fs.c b/src/win/fs.c index 94da2919..9c112b80 100644 --- a/src/win/fs.c +++ b/src/win/fs.c @@ -294,6 +294,7 @@ void fs__read(uv_fs_t* req, uv_file file, void *buf, size_t length, OVERLAPPED overlapped, *overlapped_ptr; LARGE_INTEGER offset_; DWORD bytes; + DWORD error; VERIFY_UV_FILE(file, req); @@ -323,7 +324,12 @@ void fs__read(uv_fs_t* req, uv_file file, void *buf, size_t length, if (ReadFile(handle, buf, length, &bytes, overlapped_ptr)) { SET_REQ_RESULT(req, bytes); } else { - SET_REQ_WIN32_ERROR(req, GetLastError()); + error = GetLastError(); + if (error == ERROR_HANDLE_EOF) { + SET_REQ_RESULT(req, bytes); + } else { + SET_REQ_WIN32_ERROR(req, error); + } } }