summaryrefslogtreecommitdiff
path: root/io.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-03-19 11:40:38 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-03-19 11:40:38 +0000
commitc4049f4cb6d27ffdfe9f15f4a9ddc5a48271ecf3 (patch)
tree98df695950d4ad9be608b21479593d4825e293d9 /io.c
parentb7800329d3070a4fb9f9dbdbe8b411c5f628f942 (diff)
* 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] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@23006 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'io.c')
-rw-r--r--io.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/io.c b/io.c
index 0464e5b4c5..47f0367415 100644
--- a/io.c
+++ b/io.c
@@ -110,6 +110,8 @@ extern void Init_File(void);
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 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
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 @@ io_readpartial(int argc, VALUE *argv, VALUE io)
* 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 @@ io_read_nonblock(int argc, VALUE *argv, VALUE io)
* 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 @@ io_read_nonblock(int argc, VALUE *argv, VALUE io)
*
* 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 @@ rb_io_write_nonblock(VALUE io, VALUE str)
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 @@ Init_IO(void)
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);