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

ruby-changes:11385

From: akr <ko1@a...>
Date: Thu, 19 Mar 2009 20:42:18 +0900 (JST)
Subject: [ruby-changes:11385] Ruby:r23006 (trunk): * io.c (rb_mWaitReadable): defined.

akr	2009-03-19 20:40:38 +0900 (Thu, 19 Mar 2009)

  New Revision: 23006

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

  Log:
    * io.c (rb_mWaitReadable): defined.
      (rb_mWaitWritable): defined.
      (io_getpartial): extend IO::WaitReadable on EWOULDBLOCK and EAGAIN.
      (rb_io_write_nonblock): extend IO::WaitWritable on EWOULDBLOCK and
      EAGAIN.
    * error.c (make_errno_exc): extracted from rb_sys_fail.
      (rb_mod_sys_fail): new function.
    
    * include/ruby/ruby.h (rb_mod_sys_fail): declared.
      (rb_mWaitReadable): declared.
      (rb_mWaitWritable): declared.
    
    * ext/socket/init.c (rsock_s_recvfrom_nonblock): extend
      IO::WaitReadable on EWOULDBLOCK and EAGAIN.
      (rsock_s_accept_nonblock): extend IO::WaitReadable on EWOULDBLOCK,
      EAGAIN, ECONNABORTED and EPROTO.
    
    * ext/socket/socket.c (sock_connect_nonblock): extend IO::WaitWritable
      on EINPROGRESS.
    
    * ext/socket/ancdata.c (bsock_sendmsg_internal): extend
      IO::WaitWritable on EWOULDBLOCK and EAGAIN.
      (bsock_recvmsg_internal): extend IO::WaitReadable on EWOULDBLOCK and
      EAGAIN.
    
    * ext/openssl/ossl_ssl.c (ossl_ssl_read_internal): raise SSLError
      extended by IO::WaitReadable/IO::WaitWritable on
      SSL_ERROR_WANT_READ/SSL_ERROR_WANT_WRITE.
    
    * ext/openssl/ossl.c (ossl_make_error): extracted from ossl_raise.
      (ossl_exc_new): new function.
    
    * ext/openssl/ossl.h (ossl_exc_new): declared.
    
    * lib/net/protocol.rb (rbuf_fill): rescue IO::WaitReadable and
      IO::WaitWritable.
    
      [ruby-core:22539], [ruby-dev:38140]

  Modified files:
    trunk/ChangeLog
    trunk/error.c
    trunk/ext/openssl/ossl.c
    trunk/ext/openssl/ossl.h
    trunk/ext/openssl/ossl_ssl.c
    trunk/ext/socket/ancdata.c
    trunk/ext/socket/basicsocket.c
    trunk/ext/socket/init.c
    trunk/ext/socket/socket.c
    trunk/ext/socket/tcpserver.c
    trunk/ext/socket/udpsocket.c
    trunk/ext/socket/unixserver.c
    trunk/include/ruby/ruby.h
    trunk/io.c
    trunk/lib/net/protocol.rb
    trunk/test/openssl/test_pair.rb
    trunk/test/openssl/test_ssl.rb
    trunk/test/ruby/test_io.rb
    trunk/test/socket/test_addrinfo.rb
    trunk/test/socket/test_nonblock.rb

Index: include/ruby/ruby.h
===================================================================
--- include/ruby/ruby.h	(revision 23005)
+++ include/ruby/ruby.h	(revision 23006)
@@ -986,6 +986,7 @@
 PRINTF_ARGS(NORETURN(void rb_fatal(const char*, ...)), 1, 2);
 PRINTF_ARGS(NORETURN(void rb_bug(const char*, ...)), 1, 2);
 NORETURN(void rb_sys_fail(const char*));
+NORETURN(void rb_mod_sys_fail(VALUE, const char*));
 NORETURN(void rb_iter_break(void));
 NORETURN(void rb_exit(int));
 NORETURN(void rb_notimplement(void));
@@ -1040,6 +1041,8 @@
 RUBY_EXTERN VALUE rb_mGC;
 RUBY_EXTERN VALUE rb_mMath;
 RUBY_EXTERN VALUE rb_mProcess;
+RUBY_EXTERN VALUE rb_mWaitReadable;
+RUBY_EXTERN VALUE rb_mWaitWritable;
 
 RUBY_EXTERN VALUE rb_cBasicObject;
 RUBY_EXTERN VALUE rb_cObject;
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 23005)
+++ ChangeLog	(revision 23006)
@@ -1,3 +1,45 @@
+Thu Mar 19 20:29:40 2009  Tanaka Akira  <akr@f...>
+
+	* io.c (rb_mWaitReadable): defined.
+	  (rb_mWaitWritable): defined.
+	  (io_getpartial): extend IO::WaitReadable on EWOULDBLOCK and EAGAIN.
+	  (rb_io_write_nonblock): extend IO::WaitWritable on EWOULDBLOCK and
+	  EAGAIN.
+
+	* error.c (make_errno_exc): extracted from rb_sys_fail.
+	  (rb_mod_sys_fail): new function.
+
+	* include/ruby/ruby.h (rb_mod_sys_fail): declared.
+	  (rb_mWaitReadable): declared.
+	  (rb_mWaitWritable): declared.
+
+	* ext/socket/init.c (rsock_s_recvfrom_nonblock): extend
+	  IO::WaitReadable on EWOULDBLOCK and EAGAIN.
+	  (rsock_s_accept_nonblock): extend IO::WaitReadable on EWOULDBLOCK,
+	  EAGAIN, ECONNABORTED and EPROTO.
+
+	* ext/socket/socket.c (sock_connect_nonblock): extend IO::WaitWritable
+	  on EINPROGRESS.
+
+	* ext/socket/ancdata.c (bsock_sendmsg_internal): extend
+	  IO::WaitWritable on EWOULDBLOCK and EAGAIN.
+	  (bsock_recvmsg_internal): extend IO::WaitReadable on EWOULDBLOCK and
+	  EAGAIN.
+
+	* ext/openssl/ossl_ssl.c (ossl_ssl_read_internal): raise SSLError
+	  extended by IO::WaitReadable/IO::WaitWritable on
+	  SSL_ERROR_WANT_READ/SSL_ERROR_WANT_WRITE.
+
+	* ext/openssl/ossl.c (ossl_make_error): extracted from ossl_raise.
+	  (ossl_exc_new): new function.
+
+	* ext/openssl/ossl.h (ossl_exc_new): declared.
+
+	* lib/net/protocol.rb (rbuf_fill): rescue IO::WaitReadable and
+	  IO::WaitWritable.
+
+	  [ruby-core:22539], [ruby-dev:38140] 
+
 Wed Mar 18 16:59:48 2009  Kazuhiro NISHIYAMA  <zn@m...>
 
 	* test/test_syslog.rb (TestSyslog#test_open): check
Index: io.c
===================================================================
--- io.c	(revision 23005)
+++ io.c	(revision 23006)
@@ -110,6 +110,8 @@
 VALUE rb_cIO;
 VALUE rb_eEOFError;
 VALUE rb_eIOError;
+VALUE rb_mWaitReadable;
+VALUE rb_mWaitWritable;
 
 VALUE rb_stdin, rb_stdout, rb_stderr;
 VALUE rb_deferr;		/* rescue VIM plugin */
@@ -1754,8 +1756,8 @@
         if (n < 0) {
             if (!nonblock && rb_io_wait_readable(fptr->fd))
                 goto again;
-            if (nonblock && errno == EWOULDBLOCK)
-                rb_sys_fail("WANT_READ");
+            if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN))
+                rb_mod_sys_fail(rb_mWaitReadable, "read would block");
             rb_sys_fail_path(fptr->pathv);
         }
 	else if (n == 0) {
@@ -1855,20 +1857,24 @@
  *  It causes all errors the read(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc.
  *  The caller should care such errors.
  *
+ *  If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
+ *  it is extended by IO::WaitReadable.
+ *  So IO::WaitReadable can be used to rescue the exceptions for retrying read_nonblock.
+ *
  *  read_nonblock causes EOFError on EOF.
  *
  *  If the read buffer is not empty,
  *  read_nonblock reads from the buffer like readpartial.
  *  In this case, the read(2) system call is not called.
  *
- *  When read_nonblock raises EWOULDBLOCK,
+ *  When read_nonblock raises an exception kind of IO::WaitReadable,
  *  read_nonblock should not be called
  *  until io is readable for avoiding busy loop.
  *  This can be done as follows.
  *
  *    begin
  *      result = io.read_nonblock(maxlen)
- *    rescue Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EINTR
+ *    rescue IO::WaitReadable, Errno::EINTR
  *      IO.select([io])
  *      retry
  *    end
@@ -1904,6 +1910,10 @@
  *  The result may also be smaller than string.length (partial write).
  *  The caller should care such errors and partial write.
  *
+ *  If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
+ *  it is extended by IO::WaitWritable.
+ *  So IO::WaitWritable can be used to rescue the exceptions for retrying write_nonblock.
+ *
  *    # Creates a pipe.
  *    r, w = IO.pipe
  *
@@ -1917,14 +1927,14 @@
  *
  *  If the write buffer is not empty, it is flushed at first.
  *
- *  When write_nonblock raises EWOULDBLOCK,
+ *  When write_nonblock raises an exception kind of IO::WaitWritable,
  *  write_nonblock should not be called
  *  until io is writable for avoiding busy loop.
  *  This can be done as follows.
  *
  *    begin
  *      result = io.write_nonblock(string)
- *    rescue Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EINTR
+ *    rescue IO::WaitWritable, Errno::EINTR
  *      IO.select(nil, [io])
  *      retry
  *    end
@@ -1955,8 +1965,8 @@
     n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
 
     if (n == -1) {
-        if (errno == EWOULDBLOCK)
-            rb_sys_fail("WANT_WRITE");
+        if (errno == EWOULDBLOCK || errno == EAGAIN)
+            rb_mod_sys_fail(rb_mWaitWritable, "write would block");
         rb_sys_fail_path(fptr->pathv);
     }
 
@@ -8673,6 +8683,9 @@
     rb_cIO = rb_define_class("IO", rb_cObject);
     rb_include_module(rb_cIO, rb_mEnumerable);
 
+    rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
+    rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
+
 #if 0
     /* This is necessary only for forcing rdoc handle File::open */
     rb_define_singleton_method(rb_cFile, "open",  rb_io_s_open, -1);
Index: lib/net/protocol.rb
===================================================================
--- lib/net/protocol.rb	(revision 23005)
+++ lib/net/protocol.rb	(revision 23006)
@@ -133,12 +133,20 @@
     def rbuf_fill
       begin
         @rbuf << @io.read_nonblock(BUFSIZE)
-      rescue Errno::EWOULDBLOCK
+      rescue IO::WaitReadable
         if IO.select([@io], nil, nil, @read_timeout)
           retry
         else
           raise Timeout::TimeoutError
         end
+      rescue IO::WaitWritable
+        # OpenSSL::Buffering#read_nonblock may fail with IO::WaitWritable.
+        # http://www.openssl.org/support/faq.html#PROG10
+        if IO.select(nil, [@io], nil, @read_timeout)
+          retry
+        else
+          raise Timeout::TimeoutError
+        end
       end
     end
 
Index: ext/openssl/ossl_ssl.c
===================================================================
--- ext/openssl/ossl_ssl.c	(revision 23005)
+++ ext/openssl/ossl_ssl.c	(revision 23006)
@@ -1114,15 +1114,17 @@
 		rb_eof_error();
 	    case SSL_ERROR_WANT_WRITE:
                 if (nonblock) {
-                    errno = EWOULDBLOCK;
-                    rb_sys_fail("SSL_ERROR_WANT_WRITE");
+                    VALUE exc = ossl_exc_new(eSSLError, "write would block");
+                    rb_extend_object(exc, rb_mWaitWritable);
+                    rb_exc_raise(exc);
                 }
                 rb_io_wait_writable(FPTR_TO_FD(fptr));
                 continue;
 	    case SSL_ERROR_WANT_READ:
                 if (nonblock) {
-                    errno = EWOULDBLOCK;
-                    rb_sys_fail("SSL_ERROR_WANT_READ");
+                    VALUE exc = ossl_exc_new(eSSLError, "read would block");
+                    rb_extend_object(exc, rb_mWaitReadable);
+                    rb_exc_raise(exc);
                 }
                 rb_io_wait_readable(FPTR_TO_FD(fptr));
 		continue;
Index: ext/openssl/ossl.c
===================================================================
--- ext/openssl/ossl.c	(revision 23005)
+++ ext/openssl/ossl.c	(revision 23006)
@@ -272,10 +272,9 @@
 /*
  * Errors
  */
-void
-ossl_raise(VALUE exc, const char *fmt, ...)
+static VALUE
+ossl_make_error(VALUE exc, const char *fmt, va_list args)
 {
-    va_list args;
     char buf[BUFSIZ];
     const char *msg;
     long e;
@@ -287,9 +286,7 @@
     e = ERR_peek_error();
 #endif
     if (fmt) {
-	va_start(args, fmt);
 	len = vsnprintf(buf, BUFSIZ, fmt, args);
-	va_end(args);
     }
     if (len < BUFSIZ && e) {
 	if (dOSSL == Qtrue) /* FULL INFO */
@@ -306,9 +303,31 @@
     ERR_clear_error();
 
     if(len > BUFSIZ) len = strlen(buf);
-    rb_exc_raise(rb_exc_new(exc, buf, len));
+    return rb_exc_new(exc, buf, len);
 }
 
+void
+ossl_raise(VALUE exc, const char *fmt, ...)
+{
+    va_list args;
+    VALUE err;
+    va_start(args, fmt);
+    err = ossl_make_error(exc, fmt, args);
+    va_end(args);
+    rb_exc_raise(err);
+}
+
+VALUE
+ossl_exc_new(VALUE exc, const char *fmt, ...)
+{
+    va_list args;
+    VALUE err;
+    va_start(args, fmt);
+    err = ossl_make_error(exc, fmt, args);
+    va_end(args);
+    return err;
+}
+
 /*
  * call-seq:
  *   OpenSSL.errors -> [String...]
Index: ext/openssl/ossl.h
===================================================================
--- ext/openssl/ossl.h	(revision 23005)
+++ ext/openssl/ossl.h	(revision 23006)
@@ -135,6 +135,7 @@
  */
 #define OSSL_ErrMsg() ERR_reason_error_string(ERR_get_error())
 NORETURN(void ossl_raise(VALUE, const char *, ...));
+VALUE ossl_exc_new(VALUE, const char *, ...);
 
 /*
  * Verify callback
Index: ext/socket/udpsocket.c
===================================================================
--- ext/socket/udpsocket.c	(revision 23005)
+++ ext/socket/udpsocket.c	(revision 23006)
@@ -218,8 +218,12 @@
  * 	s2.connect(*s1.addr.values_at(3,1))
  * 	s1.connect(*s2.addr.values_at(3,1))
  * 	s1.send "aaa", 0
- * 	IO.select([s2]) # emulate blocking recvfrom
- * 	p s2.recvfrom_nonblock(10)  #=> ["aaa", ["AF_INET", 33302, "localhost.localdomain", "127.0.0.1"]]
+ * 	begin # emulate blocking recvfrom
+ * 	  p s2.recvfrom_nonblock(10)  #=> ["aaa", ["AF_INET", 33302, "localhost.localdomain", "127.0.0.1"]]
+ * 	rescue IO::WaitReadable
+ * 	  IO.select([s2])
+ * 	  retry
+ * 	end
  *
  * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
  * to _recvfrom_nonblock_ fails. 
@@ -227,6 +231,10 @@
  * UDPSocket#recvfrom_nonblock may raise any error corresponding to recvfrom(2) failure,
  * including Errno::EWOULDBLOCK.
  *
+ * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
+ * it is extended by IO::WaitReadable.
+ * So IO::WaitReadable can be used to rescue the exceptions for retrying recvfrom_nonblock.
+ *
  * === See
  * * Socket#recvfrom
  */
Index: ext/socket/init.c
===================================================================
--- ext/socket/init.c	(revision 23005)
+++ ext/socket/init.c	(revision 23006)
@@ -200,7 +200,7 @@
 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
 	  case EWOULDBLOCK:
 #endif
-            rb_sys_fail("recvfrom(2) WANT_READ");
+            rb_mod_sys_fail(rb_mWaitReadable, "recvfrom(2) would block");
 	}
 	rb_sys_fail("recvfrom(2)");
     }
@@ -470,7 +470,7 @@
 #if defined EPROTO
 	  case EPROTO:
 #endif
-            rb_sys_fail("accept(2) WANT_READ");
+            rb_mod_sys_fail(rb_mWaitReadable, "accept(2) would block");
 	}
         rb_sys_fail("accept(2)");
     }
Index: ext/socket/unixserver.c
===================================================================
--- ext/socket/unixserver.c	(revision 23005)
+++ ext/socket/unixserver.c	(revision 23006)
@@ -70,7 +70,7 @@
  * 	serv = UNIXServer.new("/tmp/sock")
  * 	begin # emulate blocking accept
  * 	  sock = serv.accept_nonblock
- * 	rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
+ * 	rescue IO::WaitReadable, Errno::EINTR
  * 	  IO.select([serv])
  * 	  retry
  * 	end
@@ -81,6 +81,10 @@
  *
  * UNIXServer#accept_nonblock may raise any error corresponding to accept(2) failure,
  * including Errno::EWOULDBLOCK.
+ *
+ * If the exception is Errno::EWOULDBLOCK, Errno::AGAIN, Errno::ECONNABORTED or Errno::EPROTO,
+ * it is extended by IO::WaitReadable.
+ * So IO::WaitReadable can be used to rescue the exceptions for retrying accept_nonblock.
  * 
  * === See
  * * UNIXServer#accept
Index: ext/socket/tcpserver.c
===================================================================
--- ext/socket/tcpserver.c	(revision 23005)
+++ ext/socket/tcpserver.c	(revision 23006)
@@ -69,7 +69,7 @@
  * 	serv = TCPServer.new(2202)
  * 	begin # emulate blocking accept
  * 	  sock = serv.accept_nonblock
- * 	rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
+ * 	rescue IO::WaitReadable, Errno::EINTR
  * 	  IO.select([serv])
  * 	  retry
  * 	end
@@ -80,6 +80,10 @@
  *
  * TCPServer#accept_nonblock may raise any error corresponding to accept(2) failure,
  * including Errno::EWOULDBLOCK.
+ *
+ * If the exception is Errno::EWOULDBLOCK, Errno::AGAIN, Errno::ECONNABORTED, Errno::EPROTO,
+ * it is extended by IO::WaitReadable.
+ * So IO::WaitReadable can be used to rescue the exceptions for retrying accept_nonblock.
  * 
  * === See
  * * TCPServer#accept
Index: ext/socket/socket.c
===================================================================
--- ext/socket/socket.c	(revision 23005)
+++ ext/socket/socket.c	(revision 23006)
@@ -280,7 +280,7 @@
  * 	sockaddr = Socket.sockaddr_in(80, 'www.google.com')
  * 	begin # emulate blocking connect
  * 	  socket.connect_nonblock(sockaddr)
- * 	rescue Errno::EINPROGRESS
+ * 	rescue IO::WaitWritable
  * 	  IO.select(nil, [socket]) # wait 3-way handshake completion
  * 	  begin
  * 	    socket.connect_nonblock(sockaddr) # check connection failure 
@@ -296,6 +296,10 @@
  * Socket#connect_nonblock may raise any error corresponding to connect(2) failure,
  * including Errno::EINPROGRESS.
  *
+ * If the exception is Errno::EINPROGRESS,
+ * it is extended by IO::WaitWritable.
+ * So IO::WaitWritable can be used to rescue the exceptions for retrying connect_nonblock.
+ *
  * === See
  * * Socket#connect
  */
@@ -312,7 +316,7 @@
     n = connect(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_LEN(addr));
     if (n < 0) {
         if (errno == EINPROGRESS)
-            rb_sys_fail("connect(2) WANT_WRITE");
+            rb_mod_sys_fail(rb_mWaitWritable, "connect(2) would block");
 	rb_sys_fail("connect(2)");
     }
 
@@ -638,7 +642,7 @@
  * 	client, client_sockaddr = socket.accept
  * 	begin # emulate blocking recvfrom
  * 	  pair = client.recvfrom_nonblock(20)
- * 	rescue Errno::EAGAIN, Errno::EWOULDBLOCK
+ * 	rescue IO::WaitReadable
  * 	  IO.select([client])
  * 	  retry
  * 	end
@@ -662,6 +666,10 @@
  * Socket#recvfrom_nonblock may raise any error corresponding to recvfrom(2) failure,
  * including Errno::EWOULDBLOCK.
  *
+ * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
+ * it is extended by IO::WaitReadable.
+ * So IO::WaitReadable can be used to rescue the exceptions for retrying recvfrom_nonblock.
+ *
  * === See
  * * Socket#recvfrom
  */
@@ -720,7 +728,7 @@
  * 	socket.listen(5)
  * 	begin # emulate blocking accept
  * 	  client_socket, client_sockaddr = socket.accept_nonblock
- * 	rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
+ * 	rescue IO::WaitReadable, Errno::EINTR
  * 	  IO.select([socket])
  * 	  retry
  * 	end
@@ -743,6 +751,10 @@
  *
  * Socket#accept_nonblock may raise any error corresponding to accept(2) failure,
  * including Errno::EWOULDBLOCK.
+ *
+ * If the exception is Errno::EWOULDBLOCK, Errno::AGAIN, Errno::ECONNABORTED or Errno::EPROTO,
+ * it is extended by IO::WaitReadable.
+ * So IO::WaitReadable can be used to rescue the exceptions for retrying accept_nonblock.
  * 
  * === See
  * * Socket#accept
Index: ext/socket/basicsocket.c
===================================================================
--- ext/socket/basicsocket.c	(revision 23005)
+++ ext/socket/basicsocket.c	(revision 23006)
@@ -623,8 +623,12 @@
  * 	c = TCPSocket.new(addr, port)
  * 	s = serv.accept
  * 	c.send "aaa", 0
- * 	IO.select([s]) # emulate blocking recv.
- * 	p s.recv_nonblock(10) #=> "aaa"
+ * 	begin # emulate blocking recv.
+ * 	  p s.recv_nonblock(10) #=> "aaa"
+ * 	rescue IO::WaitReadable
+ * 	  IO.select([s])
+ * 	  retry
+ * 	end
  *
  * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
  * to _recv_nonblock_ fails. 
@@ -632,6 +636,10 @@
  * BasicSocket#recv_nonblock may raise any error corresponding to recvfrom(2) failure,
  * including Errno::EWOULDBLOCK.
  *
+ * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
+ * it is extended by IO::WaitReadable.
+ * So IO::WaitReadable can be used to rescue the exceptions for retrying recv_nonblock.
+ *
  * === See
  * * Socket#recvfrom
  */
Index: ext/socket/ancdata.c
===================================================================
--- ext/socket/ancdata.c	(revision 23005)
+++ ext/socket/ancdata.c	(revision 23006)
@@ -1279,8 +1279,8 @@
     }
 
     if (ss == -1) {
-        if (nonblock && errno == EWOULDBLOCK)
-            rb_sys_fail("sendmsg(2) WANT_WRITE");
+        if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN))
+            rb_mod_sys_fail(rb_mWaitWritable, "sendmsg(2) would block");
 	rb_sys_fail("sendmsg(2)");
     }
 
@@ -1564,8 +1564,8 @@
     }
 
     if (ss == -1) {
-        if (nonblock && errno == EWOULDBLOCK)
-            rb_sys_fail("recvmsg(2) WANT_READ");
+        if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN))
+            rb_mod_sys_fail(rb_mWaitReadable, "recvmsg(2) would block");
 #if defined(HAVE_ST_MSG_CONTROL)
         if (!gc_done && (errno == EMFILE || errno == EMSGSIZE)) {
           /*
Index: error.c
===================================================================
--- error.c	(revision 23005)
+++ error.c	(revision 23006)
@@ -1131,8 +1131,8 @@
     rb_exc_fatal(rb_exc_new3(rb_eFatal, mesg));
 }
 
-void
-rb_sys_fail(const char *mesg)
+static VALUE
+make_errno_exc(const char *mesg)
 {
     int n = errno;
     VALUE arg;
@@ -1143,10 +1143,24 @@
     }
 
     arg = mesg ? rb_str_new2(mesg) : Qnil;
-    rb_exc_raise(rb_class_new_instance(1, &arg, get_syserr(n)));
+    return rb_class_new_instance(1, &arg, get_syserr(n));
 }
 
 void
+rb_sys_fail(const char *mesg)
+{
+    rb_exc_raise(make_errno_exc(mesg));
+}
+
+void
+rb_mod_sys_fail(VALUE mod, const char *mesg)
+{
+    VALUE exc = make_errno_exc(mesg);
+    rb_extend_object(exc, mod);
+    rb_exc_raise(exc);
+}
+
+void
 rb_sys_warning(const char *fmt, ...)
 {
     char buf[BUFSIZ];
Index: test/ruby/test_io.rb
===================================================================
--- test/ruby/test_io.rb	(revision 23005)
+++ test/ruby/test_io.rb	(revision 23006)
@@ -864,7 +864,7 @@
       begin
         r.read_nonblock 4096
       rescue Errno::EWOULDBLOCK
-        assert_match(/WANT_READ/, $!.message)
+        assert_kind_of(IO::WaitReadable, $!)
       end
     }
   end
@@ -877,7 +877,7 @@
           w.write_nonblock "a"*100000
         }
       rescue Errno::EWOULDBLOCK
-        assert_match(/WANT_WRITE/, $!.message)
+        assert_kind_of(IO::WaitWritable, $!)
       end
     }
   end
Index: test/openssl/test_pair.rb
===================================================================
--- test/openssl/test_pair.rb	(revision 23005)
+++ test/openssl/test_pair.rb	(revision 23006)
@@ -147,14 +147,14 @@
   def test_read_nonblock
     ssl_pair {|s1, s2|
       err = nil
-      assert_raise(Errno::EWOULDBLOCK) {
+      assert_raise(OpenSSL::SSL::SSLError) {
         begin
           s2.read_nonblock(10)
         ensure
           err = $!
         end
       }
-      assert_match(/SSL_ERROR_WANT_READ/, err.message)
+      assert_kind_of(IO::WaitReadable, err)
       s1.write "abc\ndef\n"
       IO.select([s2])
       assert_equal("ab", s2.read_nonblock(2))
Index: test/openssl/test_ssl.rb
===================================================================
--- test/openssl/test_ssl.rb	(revision 23005)
+++ test/openssl/test_ssl.rb	(revision 23006)
@@ -172,12 +172,12 @@
       ssl = OpenSSL::SSL::SSLSocket.new(sock)
       ssl.sync_close = true
       ssl.connect
-      assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { ssl.read_nonblock(100) }
+      assert_raise(IO::WaitReadable) { ssl.read_nonblock(100) }
       ssl.write("abc\n")
       IO.select [ssl]
       assert_equal('a', ssl.read_nonblock(1))
       assert_equal("bc\n", ssl.read_nonblock(100))
-      assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { ssl.read_nonblock(100) }
+      assert_raise(IO::WaitReadable) { ssl.read_nonblock(100) }
     }
   end
 
Index: test/socket/test_nonblock.rb
===================================================================
--- test/socket/test_nonblock.rb	(revision 23005)
+++ test/socket/test_nonblock.rb	(revision 23006)
@@ -12,13 +12,13 @@
     serv = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
     serv.bind(Socket.sockaddr_in(0, "127.0.0.1"))
     serv.listen(5)
-    assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { serv.accept_nonblock }
+    assert_raise(IO::WaitReadable) { serv.accept_nonblock }
     c = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
     c.connect(serv.getsockname)
     begin
       s, sockaddr = serv.accept_nonblock
-    rescue Errno::EWOULDBLOCK
-      IO.select nil, [serv]
+    rescue IO::WaitReadable
+      IO.select [serv]
       s, sockaddr = serv.accept_nonblock
     end
     assert_equal(Socket.unpack_sockaddr_in(c.getsockname), Socket.unpack_sockaddr_in(sockaddr))
@@ -57,8 +57,8 @@
     u1 = UDPSocket.new
     u2 = UDPSocket.new
     u1.bind("127.0.0.1", 0)
-    assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { u1.recvfrom_nonblock(100) }
-    assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::EINVAL) { u2.recvfrom_nonblock(100) }
+    assert_raise(IO::WaitReadable) { u1.recvfrom_nonblock(100) }
+    assert_raise(IO::WaitReadable, Errno::EINVAL) { u2.recvfrom_nonblock(100) }
     u2.send("aaa", 0, u1.getsockname)
     IO.select [u1]
     mesg, inet_addr = u1.recvfrom_nonblock(100)
@@ -67,7 +67,7 @@
     af, port, host, addr = inet_addr
     u2_port, u2_addr = Socket.unpack_sockaddr_in(u2.getsockname)
     assert_equal(u2_port, port)
-    assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { u1.recvfrom_nonblock(100) }
+    assert_raise(IO::WaitReadable) { u1.recvfrom_nonblock(100) }
     u2.send("", 0, u1.getsockname)
     assert_nothing_raised("cygwin 1.5.19 has a problem to send an empty UDP packet. [ruby-dev:28915]") {
       timeout(1) { IO.select [u1] }
@@ -83,13 +83,13 @@
     u1 = UDPSocket.new
     u2 = UDPSocket.new
     u1.bind("127.0.0.1", 0)
-    assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { u1.recv_nonblock(100) }
-    assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::EINVAL) { u2.recv_nonblock(100) }
+    assert_raise(IO::WaitReadable) { u1.recv_nonblock(100) }
+    assert_raise(IO::WaitReadable, Errno::EINVAL) { u2.recv_nonblock(100) }
     u2.send("aaa", 0, u1.getsockname)
     IO.select [u1]
     mesg = u1.recv_nonblock(100)
     assert_equal("aaa", mesg)
-    assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { u1.recv_nonblock(100) }
+    assert_raise(IO::WaitReadable) { u1.recv_nonblock(100) }
     u2.send("", 0, u1.getsockname)
     assert_nothing_raised("cygwin 1.5.19 has a problem to send an empty UDP packet. [ruby-dev:28915]") {
       timeout(1) { IO.select [u1] }
@@ -105,8 +105,8 @@
     s1 = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
     s1.bind(Socket.sockaddr_in(0, "127.0.0.1"))
     s2 = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
-    assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { s1.recvfrom_nonblock(100) }
-    assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::EINVAL) { s2.recvfrom_nonblock(100) }
+    assert_raise(IO::WaitReadable) { s1.recvfrom_nonblock(100) }
+    assert_raise(IO::WaitReadable, Errno::EINVAL) { s2.recvfrom_nonblock(100) }
     s2.send("aaa", 0, s1.getsockname)
     IO.select [s1]
     mesg, sockaddr = s1.recvfrom_nonblock(100)
@@ -140,13 +140,13 @@
 
   def test_tcp_recv_nonblock
     c, s = tcp_pair
-    assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { c.recv_nonblock(100) }
-    assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { s.recv_nonblock(100) }
+    assert_raise(IO::WaitReadable) { c.recv_nonblock(100) }
+    assert_raise(IO::WaitReadable) { s.recv_nonblock(100) }
     c.write("abc")
     IO.select [s]
     assert_equal("a", s.recv_nonblock(1))
     assert_equal("bc", s.recv_nonblock(100))
-    assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { s.recv_nonblock(100) }
+    assert_raise(IO::WaitReadable) { s.recv_nonblock(100) }
   ensure
     c.close if c
     s.close if s
@@ -154,13 +154,13 @@
 
   def test_read_nonblock
     c, s = tcp_pair
-    assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { c.read_nonblock(100) }
-    assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { s.read_nonblock(100) }
+    assert_raise(IO::WaitReadable) { c.read_nonblock(100) }
+    assert_raise(IO::WaitReadable) { s.read_nonblock(100) }
     c.write("abc")
     IO.select [s]
     assert_equal("a", s.read_nonblock(1))
     assert_equal("bc", s.read_nonblock(100))
-    assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { s.read_nonblock(100) }
+    assert_raise(IO::WaitReadable) { s.read_nonblock(100) }
   ensure
     c.close if c
     s.close if s
@@ -175,7 +175,7 @@
     ret = c.write_nonblock(str)
     assert_operator(ret, :>, 0)
     loop {
-      assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) {
+      assert_raise(IO::WaitWritable) {
         loop {
           ret = c.write_nonblock(str)
           assert_operator(ret, :>, 0)
@@ -197,7 +197,7 @@
           c.sendmsg_nonblock("a" * 100000)
         }
       rescue Errno::EWOULDBLOCK
-        assert_match(/WANT_WRITE/, $!.message)
+        assert_kind_of(IO::WaitWritable, $!)
       end
     }
   end
@@ -207,7 +207,7 @@
       begin
         c.recvmsg_nonblock(4096)
       rescue Errno::EWOULDBLOCK
-        assert_match(/WANT_READ/, $!.message)
+        assert_kind_of(IO::WaitReadable, $!)
       end
     }
   end
@@ -217,7 +217,7 @@
       begin
         c.recv_nonblock(4096)
       rescue Errno::EWOULDBLOCK
-        assert_match(/WANT_READ/, $!.message)
+        assert_kind_of(IO::WaitReadable, $!)
       end
     }
   end
@@ -229,7 +229,7 @@
     begin
       c.connect_nonblock(Socket.sockaddr_in(port, "127.0.0.1"))
     rescue Errno::EINPROGRESS
-      assert_match(/WANT_WRITE/, $!.message)
+      assert_kind_of(IO::WaitWritable, $!)
     end
   ensure
     serv.close if serv && !serv.closed?
@@ -243,8 +243,8 @@
     port = serv.local_address.ip_port
     begin
       s, _ = serv.accept_nonblock
-    rescue Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO
-      assert_match(/WANT_READ/, $!.message)
+    rescue Errno::EWOULDBLOCK
+      assert_kind_of(IO::WaitReadable, $!)
     end
   ensure
     serv.close if serv && !serv.closed?
Index: test/socket/test_addrinfo.rb
===================================================================
--- test/socket/test_addrinfo.rb	(revision 23005)
+++ test/socket/test_addrinfo.rb	(revision 23006)
@@ -236,7 +236,7 @@
     c.connect(serv.local_address)
     begin
       ret = serv.accept_nonblock
-    rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
+    rescue IO::WaitReadable, Errno::EINTR
       IO.select([serv])
       retry
     end
@@ -299,7 +299,7 @@
     s2.send("test-socket-recvfrom", 0, s1.getsockname)
     begin
       data, ai = s1.recvfrom_nonblock(100)
-    rescue Errno::EWOULDBLOCK
+    rescue IO::WaitReadable
       IO.select([s1])
       retry
     end

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

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