[前][次][番号順一覧][スレッド一覧]

ruby-changes:36280

From: usa <ko1@a...>
Date: Mon, 10 Nov 2014 19:42:34 +0900 (JST)
Subject: [ruby-changes:36280] usa:r48361 (trunk): * win32/win32.c, include/win32/win32.h (rb_w32_set_nonblock): new

usa	2014-11-10 19:42:19 +0900 (Mon, 10 Nov 2014)

  New Revision: 48361

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=48361

  Log:
    * 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.

  Modified files:
    trunk/ChangeLog
    trunk/ext/io/nonblock/nonblock.c
    trunk/include/ruby/win32.h
    trunk/io.c
    trunk/test/ruby/test_io.rb
    trunk/win32/win32.c
Index: include/ruby/win32.h
===================================================================
--- include/ruby/win32.h	(revision 48360)
+++ include/ruby/win32.h	(revision 48361)
@@ -327,6 +327,7 @@ extern rb_pid_t rb_w32_uaspawn(int, cons https://github.com/ruby/ruby/blob/trunk/include/ruby/win32.h#L327
 extern rb_pid_t rb_w32_uaspawn_flags(int, const char *, char *const *, DWORD);
 extern int kill(int, int);
 extern int fcntl(int, int, ...);
+extern int rb_w32_set_nonblock(int);
 extern rb_pid_t rb_w32_getpid(void);
 extern rb_pid_t rb_w32_getppid(void);
 #if !defined(__BORLANDC__)
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 48360)
+++ ChangeLog	(revision 48361)
@@ -1,3 +1,21 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Mon Nov 10 19:37:09 2014  NAKAMURA Usaku  <usa@r...>
+
+	* 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.
+
 Mon Nov 10 17:24:34 2014  Nobuyoshi Nakada  <nobu@r...>
 
 	* ext/etc/etc.c (etc_getlogin): set login name encoding properly.
Index: io.c
===================================================================
--- io.c	(revision 48360)
+++ io.c	(revision 48361)
@@ -2474,6 +2474,11 @@ read_all(rb_io_t *fptr, long siz, VALUE https://github.com/ruby/ruby/blob/trunk/io.c#L2474
 void
 rb_io_set_nonblock(rb_io_t *fptr)
 {
+#ifdef _WIN32
+    if (rb_w32_set_nonblock(fptr->fd) != 0) {
+	rb_sys_fail_path(fptr->pathv);
+    }
+#else
     int oflags;
 #ifdef F_GETFL
     oflags = fcntl(fptr->fd, F_GETFL);
@@ -2489,6 +2494,7 @@ rb_io_set_nonblock(rb_io_t *fptr) https://github.com/ruby/ruby/blob/trunk/io.c#L2494
             rb_sys_fail_path(fptr->pathv);
         }
     }
+#endif
 }
 
 void
Index: win32/win32.c
===================================================================
--- win32/win32.c	(revision 48360)
+++ win32/win32.c	(revision 48361)
@@ -4122,6 +4122,33 @@ fcntl(int fd, int cmd, ...) https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L4122
     }
 }
 
+/* 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 si https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L6381
 
     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, si https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L6555
 	if (size > 0)
 	    goto retry;
     }
+    if (ret == 0) {
+	ret = -1;
+	errno = EWOULDBLOCK;
+    }
 
     MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
 
Index: ext/io/nonblock/nonblock.c
===================================================================
--- ext/io/nonblock/nonblock.c	(revision 48360)
+++ ext/io/nonblock/nonblock.c	(revision 48361)
@@ -79,7 +79,10 @@ rb_io_nonblock_set(VALUE io, VALUE nb) https://github.com/ruby/ruby/blob/trunk/ext/io/nonblock/nonblock.c#L79
 {
     rb_io_t *fptr;
     GetOpenFile(io, fptr);
-    io_nonblock_set(fptr->fd, io_nonblock_mode(fptr->fd), RTEST(nb));
+    if (RTEST(nb))
+	rb_io_set_nonblock(fptr);
+    else
+	io_nonblock_set(fptr->fd, io_nonblock_mode(fptr->fd), RTEST(nb));
     return io;
 }
 
Index: test/ruby/test_io.rb
===================================================================
--- test/ruby/test_io.rb	(revision 48360)
+++ test/ruby/test_io.rb	(revision 48361)
@@ -1259,7 +1259,6 @@ class TestIO < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_io.rb#L1259
   end
 
   def test_write_nonblock
-    skip "IO#write_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
     pipe(proc do |w|
       w.write_nonblock(1)
       w.close
@@ -1269,7 +1268,6 @@ class TestIO < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_io.rb#L1268
   end
 
   def test_read_nonblock_with_not_empty_buffer
-    skip "IO#read_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
     with_pipe {|r, w|
       w.write "foob"
       w.close
@@ -1279,7 +1277,6 @@ class TestIO < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_io.rb#L1277
   end
 
   def test_write_nonblock_simple_no_exceptions
-    skip "IO#write_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
     pipe(proc do |w|
       w.write_nonblock('1', exception: false)
       w.close
@@ -1290,7 +1287,6 @@ class TestIO < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_io.rb#L1287
 
   def test_read_nonblock_error
     return if !have_nonblock?
-    skip "IO#read_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
     with_pipe {|r, w|
       begin
         r.read_nonblock 4096
@@ -1310,7 +1306,6 @@ class TestIO < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_io.rb#L1306
 
   def test_read_nonblock_no_exceptions
     return if !have_nonblock?
-    skip "IO#read_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
     with_pipe {|r, w|
       assert_equal :wait_readable, r.read_nonblock(4096, exception: false)
       w.puts "HI!"
@@ -1322,7 +1317,6 @@ class TestIO < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_io.rb#L1317
 
   def test_read_nonblock_with_buffer_no_exceptions
     return if !have_nonblock?
-    skip "IO#read_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
     with_pipe {|r, w|
       assert_equal :wait_readable, r.read_nonblock(4096, "", exception: false)
       w.puts "HI!"
@@ -1337,7 +1331,6 @@ class TestIO < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_io.rb#L1331
 
   def test_write_nonblock_error
     return if !have_nonblock?
-    skip "IO#write_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
     with_pipe {|r, w|
       begin
         loop {
@@ -1351,7 +1344,6 @@ class TestIO < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_io.rb#L1344
 
   def test_write_nonblock_no_exceptions
     return if !have_nonblock?
-    skip "IO#write_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
     with_pipe {|r, w|
       loop {
         ret = w.write_nonblock("a"*100000, exception: false)
@@ -2643,7 +2635,6 @@ End https://github.com/ruby/ruby/blob/trunk/test/ruby/test_io.rb#L2635
   end
 
   def test_cross_thread_close_fd
-    skip "cross thread close causes hung-up if pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
     with_pipe do |r,w|
       read_thread = Thread.new do
         begin
@@ -2932,7 +2923,6 @@ End https://github.com/ruby/ruby/blob/trunk/test/ruby/test_io.rb#L2923
   end
 
   def test_readpartial_locktmp
-    skip "nonblocking mode is not supported for pipe on this platform" if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
     bug6099 = '[ruby-dev:45297]'
     buf = " " * 100
     data = "a" * 100

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]