Feature #6154 » eagain_readwrite.diff
| error.c | ||
|---|---|---|
| 
     #define WEXITSTATUS(status) (status) 
   | 
||
| 
     #endif 
   | 
||
| 
     VALUE rb_eEAGAIN; 
   | 
||
| 
     VALUE rb_eEWOULDBLOCK; 
   | 
||
| 
     extern const char ruby_description[]; 
   | 
||
| 
     #define REPORTBUG_MSG \ 
   | 
||
| ... | ... | |
| 
         if (!st_lookup(syserr_tbl, n, &error)) { 
   | 
||
| 
     	error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError); 
   | 
||
| 
     | 
||
| 
     	if (n == EAGAIN) { 
   | 
||
| 
     	    rb_eEAGAIN = error; 
   | 
||
| 
     		if (n == EWOULDBLOCK) rb_eEWOULDBLOCK = error; /* same value */ 
   | 
||
| 
     	} 
   | 
||
| 
     	else if (n == EWOULDBLOCK) { /* different error */ 
   | 
||
| 
     	    rb_eEWOULDBLOCK = error; 
   | 
||
| 
     	} 
   | 
||
| 
     | 
||
| 
     	rb_define_const(error, "Errno", INT2NUM(n)); 
   | 
||
| 
     	st_add_direct(syserr_tbl, n, error); 
   | 
||
| 
         } 
   | 
||
| ext/socket/ancdata.c | ||
|---|---|---|
| 
         if (ss == -1) { 
   | 
||
| 
             if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN)) 
   | 
||
| 
                 rb_mod_sys_fail(rb_mWaitWritable, "sendmsg(2) would block"); 
   | 
||
| 
                 rb_readwrite_sys_fail(1, "sendmsg(2) would block"); 
   | 
||
| 
     	rb_sys_fail("sendmsg(2)"); 
   | 
||
| 
         } 
   | 
||
| ... | ... | |
| 
         if (ss == -1) { 
   | 
||
| 
             if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN)) 
   | 
||
| 
                 rb_mod_sys_fail(rb_mWaitReadable, "recvmsg(2) would block"); 
   | 
||
| 
                 rb_readwrite_sys_fail(0, "recvmsg(2) would block"); 
   | 
||
| 
     #if defined(HAVE_ST_MSG_CONTROL) 
   | 
||
| 
             if (!gc_done && (errno == EMFILE || errno == EMSGSIZE)) { 
   | 
||
| 
               /* 
   | 
||
| ext/socket/init.c | ||
|---|---|---|
| 
     #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN 
   | 
||
| 
     	  case EWOULDBLOCK: 
   | 
||
| 
     #endif 
   | 
||
| 
                 rb_mod_sys_fail(rb_mWaitReadable, "recvfrom(2) would block"); 
   | 
||
| 
                 rb_readwrite_sys_fail(0, "recvfrom(2) would block"); 
   | 
||
| 
     	} 
   | 
||
| 
     	rb_sys_fail("recvfrom(2)"); 
   | 
||
| 
         } 
   | 
||
| ... | ... | |
| 
     #if defined EPROTO 
   | 
||
| 
     	  case EPROTO: 
   | 
||
| 
     #endif 
   | 
||
| 
                 rb_mod_sys_fail(rb_mWaitReadable, "accept(2) would block"); 
   | 
||
| 
                 rb_readwrite_sys_fail(0, "accept(2) would block"); 
   | 
||
| 
     	} 
   | 
||
| 
             rb_sys_fail("accept(2)"); 
   | 
||
| 
         } 
   | 
||
| include/ruby/ruby.h | ||
|---|---|---|
| 
     NORETURN(void rb_sys_fail_str(VALUE)); 
   | 
||
| 
     NORETURN(void rb_mod_sys_fail(VALUE, const char*)); 
   | 
||
| 
     NORETURN(void rb_mod_sys_fail_str(VALUE, VALUE)); 
   | 
||
| 
     NORETURN(void rb_readwrite_sys_fail(int, const char*)); 
   | 
||
| 
     NORETURN(void rb_iter_break(void)); 
   | 
||
| 
     NORETURN(void rb_iter_break_value(VALUE)); 
   | 
||
| 
     NORETURN(void rb_exit(int)); 
   | 
||
| io.c | ||
|---|---|---|
| 
     VALUE rb_eIOError; 
   | 
||
| 
     VALUE rb_mWaitReadable; 
   | 
||
| 
     VALUE rb_mWaitWritable; 
   | 
||
| 
     extern VALUE rb_eEAGAIN; 
   | 
||
| 
     extern VALUE rb_eEWOULDBLOCK; 
   | 
||
| 
     VALUE rb_eEAGAINReadable; 
   | 
||
| 
     VALUE rb_eEAGAINWritable; 
   | 
||
| 
     VALUE rb_eEWOULDBLOCKReadable; 
   | 
||
| 
     VALUE rb_eEWOULDBLOCKWritable; 
   | 
||
| 
     VALUE rb_stdin, rb_stdout, rb_stderr; 
   | 
||
| 
     VALUE rb_deferr;		/* rescue VIM plugin */ 
   | 
||
| ... | ... | |
| 
                 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(0, "read would block"); 
   | 
||
| 
                 rb_sys_fail_path(fptr->pathv); 
   | 
||
| 
             } 
   | 
||
| 
         } 
   | 
||
| ... | ... | |
| 
         if (n == -1) { 
   | 
||
| 
             if (errno == EWOULDBLOCK || errno == EAGAIN) 
   | 
||
| 
                 rb_mod_sys_fail(rb_mWaitWritable, "write would block"); 
   | 
||
| 
                 rb_readwrite_sys_fail(1, "write would block"); 
   | 
||
| 
             rb_sys_fail_path(fptr->pathv); 
   | 
||
| 
         } 
   | 
||
| ... | ... | |
| 
         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) { 
   | 
||
| 
     		if (n == EAGAIN) { 
   | 
||
| 
     		    rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWritable)); 
   | 
||
| 
     		} 
   | 
||
| 
     		else if (n == EWOULDBLOCK) { 
   | 
||
| 
     			rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWritable)); 
   | 
||
| 
     		} 
   | 
||
| 
     		else { 
   | 
||
| 
     			rb_mod_sys_fail_str(rb_mWaitWritable, arg); 
   | 
||
| 
     		} 
   | 
||
| 
         } 
   | 
||
| 
         else { 
   | 
||
| 
     		if (n == EAGAIN) { 
   | 
||
| 
     		    rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINReadable)); 
   | 
||
| 
     		} 
   | 
||
| 
     		else if (n == EWOULDBLOCK) { 
   | 
||
| 
     			rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKReadable)); 
   | 
||
| 
     		} 
   | 
||
| 
     		else { 
   | 
||
| 
     			rb_mod_sys_fail_str(rb_mWaitReadable, arg); 
   | 
||
| 
     		} 
   | 
||
| 
         } 
   | 
||
| 
     } 
   | 
||
| 
     /* 
   | 
||
| 
      * Document-class: IOError 
   | 
||
| 
      * 
   | 
||
| ... | ... | |
| 
         rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable"); 
   | 
||
| 
         rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable"); 
   | 
||
| 
         rb_eEAGAINReadable = rb_define_class_under(rb_cIO, "EAGAINReadable", rb_eEAGAIN); 
   | 
||
| 
         rb_include_module(rb_eEAGAINReadable, rb_mWaitReadable); 
   | 
||
| 
         rb_eEAGAINWritable = rb_define_class_under(rb_cIO, "EAGAINWritable", rb_eEAGAIN); 
   | 
||
| 
         rb_include_module(rb_eEAGAINWritable, rb_mWaitWritable); 
   | 
||
| 
         if (EAGAIN == EWOULDBLOCK) { 
   | 
||
| 
     		rb_eEWOULDBLOCKReadable = rb_eEAGAINReadable; 
   | 
||
| 
     		rb_define_const(rb_cIO, "EWOULDBLOCKReadable", rb_eEAGAINReadable); 
   | 
||
| 
     		rb_eEWOULDBLOCKWritable = rb_eEAGAINWritable; 
   | 
||
| 
     		rb_define_const(rb_cIO, "EWOULDBLOCKWritable", rb_eEAGAINWritable); 
   | 
||
| 
     	} 
   | 
||
| 
     	else { 
   | 
||
| 
     	    rb_eEWOULDBLOCKReadable = rb_define_class_under(rb_cIO, "EWOULDBLOCKReadable", rb_eEWOULDBLOCK); 
   | 
||
| 
     	    rb_include_module(rb_eEWOULDBLOCKReadable, rb_mWaitReadable); 
   | 
||
| 
     	    rb_eEWOULDBLOCKWritable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWritable", rb_eEWOULDBLOCK); 
   | 
||
| 
     	    rb_include_module(rb_eEWOULDBLOCKWritable, rb_mWaitWritable); 
   | 
||
| 
     	} 
   | 
||
| 
     #if 0 
   | 
||
| 
         /* This is necessary only for forcing rdoc handle File::open */ 
   | 
||
| test/socket/test_unix.rb | ||
|---|---|---|
| 
       def test_dgram_pair 
   | 
||
| 
         s1, s2 = UNIXSocket.pair(Socket::SOCK_DGRAM) 
   | 
||
| 
         assert_raise(Errno::EAGAIN) { s1.recv_nonblock(10) } 
   | 
||
| 
         begin 
   | 
||
| 
           s1.recv_nonblock(10) 
   | 
||
| 
           fail 
   | 
||
| 
         rescue => e 
   | 
||
| 
           assert(Errno::EAGAIN === e) 
   | 
||
| 
           assert(IO::WaitReadable === e) 
   | 
||
| 
         end 
   | 
||
| 
         s2.send("", 0) 
   | 
||
| 
         s2.send("haha", 0) 
   | 
||
| 
         s2.send("", 0) 
   | 
||