From fd9f6bde957ce681fed49182be02124ecc89b362 Mon Sep 17 00:00:00 2001 From: usa Date: Mon, 10 Nov 2014 10:42:19 +0000 Subject: * win32/win32.c, include/win32/win32.h (rb_w32_set_nonblock): new function to support nonblock-mode of pipes. * win32/win32.c (rb_w32_read): nonblock-mode pipe returns ERROR_NO_DATA if there is no data, but also returns it if remote-end is closed. * win32/win32.c (rb_w32_write): if cannot to write any data, it may be blocking. * io.c (rb_io_set_nonblock): use rb_w32_set_nonblock for Windows. * ext/io/nonblock/nonblock.c (rb_io_nonblock_set): use ruby's API when setting nonblock-mode. * test/ruby/test_io.rb: test nonblock pipes on Windows. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@48361 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- win32/win32.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'win32') diff --git a/win32/win32.c b/win32/win32.c index 9f80d3228d..2661641266 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -4122,6 +4122,33 @@ fcntl(int fd, int cmd, ...) } } +/* License: Ruby's */ +int +rb_w32_set_nonblock(int fd) +{ + SOCKET sock = TO_SOCKET(fd); + if (is_socket(sock)) { + return setfl(sock, O_NONBLOCK); + } + else if (is_pipe(sock)) { + DWORD state; + if (!GetNamedPipeHandleState((HANDLE)sock, &state, NULL, NULL, NULL, NULL, 0)) { + errno = map_errno(GetLastError()); + return -1; + } + state |= PIPE_NOWAIT; + if (!SetNamedPipeHandleState((HANDLE)sock, &state, NULL, NULL)) { + errno = map_errno(GetLastError()); + return -1; + } + return 0; + } + else { + errno = EBADF; + return -1; + } +} + #ifndef WNOHANG #define WNOHANG -1 #endif @@ -6354,7 +6381,18 @@ rb_w32_read(int fd, void *buf, size_t size) if (!ReadFile((HANDLE)_osfhnd(fd), buf, len, &read, pol)) { err = GetLastError(); - if (err != ERROR_IO_PENDING) { + if (err == ERROR_NO_DATA && (_osfile(fd) & FPIPE)) { + DWORD state; + if (GetNamedPipeHandleState((HANDLE)_osfhnd(fd), &state, NULL, NULL, NULL, NULL, 0) && (state & PIPE_NOWAIT)) { + errno = EWOULDBLOCK; + } + else { + errno = map_errno(err); + } + MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock)); + return -1; + } + else if (err != ERROR_IO_PENDING) { if (pol) CloseHandle(ol.hEvent); if (err == ERROR_ACCESS_DENIED) errno = EBADF; @@ -6517,6 +6555,10 @@ rb_w32_write(int fd, const void *buf, size_t size) if (size > 0) goto retry; } + if (ret == 0) { + ret = -1; + errno = EWOULDBLOCK; + } MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock)); -- cgit v1.2.3