summaryrefslogtreecommitdiff
path: root/io.c
diff options
context:
space:
mode:
authorheadius <headius@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-04-08 19:58:55 +0000
committerheadius <headius@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-04-08 19:58:55 +0000
commit0626d9b91c8e64dbbe90fd966ea95d2c80f9632e (patch)
tree628cf13afa093ab594e5a1b0e033f9015034c292 /io.c
parent46eddae1b486ae73480d00ebd99adb94ea04eb57 (diff)
Fix #6154 by introducing new EAGAIN/EWOULDBLOCK/EINPROGRESS
subclasses that include WaitReadable or WaitWritable rather than extending them into the exception object each time. * error.c: Capture EGAIN, EWOULDBLOCK, EINPROGRESS exceptions and export them for use in WaitReadable/Writable exceptions. * io.c: Create versions of EAGAIN, EWOULDBLOCK, EINPROGRESS that include WaitReadable and WaitWritable. Add rb_readwrite_sys_fail for nonblocking failures using those exceptions. Use that function in io_getpartial and io_write_nonblock instead of rb_mod_sys_fail * ext/openssl/ossl_ssl.c: Add new SSLError subclasses that include WaitReadable and WaitWritable. Use those classes for write_would_block and read_would_block instead of rb_mod_sys_fail. * ext/socket/ancdata.c: Use rb_readwrite_sys_fail instead of rb_mod_sys_fail in bsock_sendmsg_internal and bsock_recvmsg_internal. * ext/socket/init.c: Use rb_readwrite_sys_fail instead of rb_mod_sys_fail in rsock_s_recvfrom_nonblock and rsock_s_connect_nonblock. * ext/socket/socket.c: Use rb_readwrite_sys_fail instead of rb_mod_sys_fail in sock_connect_nonblock. * include/ruby/ruby.h: Export rb_readwrite_sys_fail for use instead of rb_mod_sys_fail. Introduce new constants RB_IO_WAIT_READABLE and RB_IO_WAIT_WRITABLE for first arg to rb_readwrite_sys_fail. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40195 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'io.c')
-rw-r--r--io.c80
1 files changed, 78 insertions, 2 deletions
diff --git a/io.c b/io.c
index ce6dc70af7..42388ac147 100644
--- a/io.c
+++ b/io.c
@@ -133,6 +133,16 @@ VALUE rb_eEOFError;
VALUE rb_eIOError;
VALUE rb_mWaitReadable;
VALUE rb_mWaitWritable;
+extern VALUE rb_eEAGAIN;
+extern VALUE rb_eEWOULDBLOCK;
+extern VALUE rb_eEINPROGRESS;
+
+static VALUE rb_eEAGAINWaitReadable;
+static VALUE rb_eEAGAINWaitWritable;
+static VALUE rb_eEWOULDBLOCKWaitReadable;
+static VALUE rb_eEWOULDBLOCKWaitWritable;
+static VALUE rb_eEINPROGRESSWaitWritable;
+static VALUE rb_eEINPROGRESSWaitReadable;
VALUE rb_stdin, rb_stdout, rb_stderr;
VALUE rb_deferr; /* rescue VIM plugin */
@@ -2355,6 +2365,9 @@ rb_io_set_nonblock(rb_io_t *fptr)
}
}
+void
+rb_readwrite_sys_fail(int writable, const char *mesg);
+
static VALUE
io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
{
@@ -2393,7 +2406,7 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
if (!nonblock && rb_io_wait_readable(fptr->fd))
goto again;
if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN))
- rb_mod_sys_fail(rb_mWaitReadable, "read would block");
+ rb_readwrite_sys_fail(RB_IO_WAIT_READABLE, "read would block");
rb_sys_fail_path(fptr->pathv);
}
}
@@ -2612,7 +2625,7 @@ rb_io_write_nonblock(VALUE io, VALUE str)
if (n == -1) {
if (errno == EWOULDBLOCK || errno == EAGAIN)
- rb_mod_sys_fail(rb_mWaitWritable, "write would block");
+ rb_readwrite_sys_fail(RB_IO_WAIT_WRITABLE, "write would block");
rb_sys_fail_path(fptr->pathv);
}
@@ -11450,6 +11463,50 @@ argf_write(VALUE argf, VALUE str)
return rb_io_write(argf_write_io(argf), str);
}
+void
+rb_readwrite_sys_fail(int writable, const char *mesg)
+{
+ VALUE arg;
+ int n = errno;
+ arg = mesg ? rb_str_new2(mesg) : Qnil;
+ if (writable == RB_IO_WAIT_WRITABLE) {
+ switch (n) {
+ case EAGAIN:
+ rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitWritable));
+ break;
+#if EAGAIN != EWOULDBLOCK
+ case EWOULDBLOCK:
+ rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitWritable));
+ break;
+#endif
+ case EINPROGRESS:
+ rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitWritable));
+ break;
+ default:
+ rb_mod_sys_fail_str(rb_mWaitWritable, arg);
+ }
+ }
+ else if (writable == RB_IO_WAIT_READABLE) {
+ switch (n) {
+ case EAGAIN:
+ rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitReadable));
+ break;
+#if EAGAIN != EWOULDBLOCK
+ case EWOULDBLOCK:
+ rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitReadable));
+ break;
+#endif
+ case EINPROGRESS:
+ rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitReadable));
+ break;
+ default:
+ rb_mod_sys_fail_str(rb_mWaitReadable, arg);
+ }
+ } else {
+ rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", writable);
+ }
+}
+
/*
* Document-class: IOError
*
@@ -11658,6 +11715,25 @@ Init_IO(void)
rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
+ rb_eEAGAINWaitReadable = rb_define_class_under(rb_cIO, "EAGAINWaitReadable", rb_eEAGAIN);
+ rb_include_module(rb_eEAGAINWaitReadable, rb_mWaitReadable);
+ rb_eEAGAINWaitWritable = rb_define_class_under(rb_cIO, "EAGAINWaitWritable", rb_eEAGAIN);
+ rb_include_module(rb_eEAGAINWaitWritable, rb_mWaitWritable);
+ if (EAGAIN == EWOULDBLOCK) {
+ rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
+ rb_define_const(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEAGAINWaitReadable);
+ rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
+ rb_define_const(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEAGAINWaitWritable);
+ } else {
+ rb_eEWOULDBLOCKWaitReadable = rb_define_class_under(rb_cIO, "EWOULDBLOCKRWaiteadable", rb_eEWOULDBLOCK);
+ rb_include_module(rb_eEWOULDBLOCKWaitReadable, rb_mWaitReadable);
+ rb_eEWOULDBLOCKWaitWritable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEWOULDBLOCK);
+ rb_include_module(rb_eEWOULDBLOCKWaitWritable, rb_mWaitWritable);
+ }
+ rb_eEINPROGRESSWaitReadable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitReadable", rb_eEINPROGRESS);
+ rb_include_module(rb_eEINPROGRESSWaitReadable, rb_mWaitReadable);
+ rb_eEINPROGRESSWaitWritable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitWritable", rb_eEINPROGRESS);
+ rb_include_module(rb_eEINPROGRESSWaitWritable, rb_mWaitWritable);
#if 0
/* This is necessary only for forcing rdoc handle File::open */