Better handling of timeout in rb_io_maybe_wait_*. (#9531)

This commit is contained in:
Samuel Williams 2024-10-04 19:36:06 +13:00 committed by GitHub
parent 96d69d2df2
commit c878843b2c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
Notes: git 2024-10-04 06:36:25 +00:00
Merged-By: ioquatix <samuel@codeotaku.com>
3 changed files with 30 additions and 15 deletions

View File

@ -975,6 +975,7 @@ VALUE rb_io_wait(VALUE io, VALUE events, VALUE timeout);
* @exception rb_eRangeError `timeout` is out of range.
* @exception rb_eSystemCallError `select(2)` failed for some reason.
* @retval RUBY_Qfalse Operation timed out.
* @retval RUBY_Qnil Operation failed for some other reason (errno).
* @retval Otherwise Actual events reached.
*
*/
@ -982,8 +983,11 @@ VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout);
/**
* Blocks until the passed IO is ready for reading, if that makes sense for the
* passed errno. This is a special case of rb_io_maybe_wait() that only
* concerns for reading.
* passed errno. This is a special case of rb_io_maybe_wait() that is
* only concerned with reading and handles the timeout.
*
* If you do not want the default timeout handling, consider using
* ::rb_io_maybe_wait directly.
*
* @param[in] error System errno.
* @param[in] io An IO object to wait.
@ -991,15 +995,18 @@ VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout);
* @exception rb_eIOError `io` is not open.
* @exception rb_eRangeError `timeout` is out of range.
* @exception rb_eSystemCallError `select(2)` failed for some reason.
* @retval 0 Operation timed out.
* @exception rb_eIOTimeoutError The wait operation timed out.
* @retval Otherwise Always returns ::RUBY_IO_READABLE.
*/
int rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout);
/**
* Blocks until the passed IO is ready for writing, if that makes sense for the
* passed errno. This is a special case of rb_io_maybe_wait() that only
* concernsfor writing.
* passed errno. This is a special case of rb_io_maybe_wait() that is
* only concerned with writing, and handles the timeout.
*
* If you do not want the default timeout handling, consider using
* ::rb_io_maybe_wait directly.
*
* @param[in] error System errno.
* @param[in] io An IO object to wait.
@ -1007,7 +1014,7 @@ int rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout);
* @exception rb_eIOError `io` is not open.
* @exception rb_eRangeError `timeout` is out of range.
* @exception rb_eSystemCallError `select(2)` failed for some reason.
* @retval 0 Operation timed out.
* @exception rb_eIOTimeoutError The wait operation timed out.
* @retval Otherwise Always returns ::RUBY_IO_WRITABLE.
*/
int rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout);

14
io.c
View File

@ -1623,7 +1623,7 @@ rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout)
default:
// Non-specific error, no event is ready:
return Qfalse;
return Qnil;
}
}
@ -1635,9 +1635,11 @@ rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout)
if (RTEST(result)) {
return RB_NUM2INT(result);
}
else {
return 0;
else if (result == RUBY_Qfalse) {
rb_raise(rb_eIOTimeoutError, "Timed out waiting for IO to become readable!");
}
return 0;
}
int
@ -1648,9 +1650,11 @@ rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout)
if (RTEST(result)) {
return RB_NUM2INT(result);
}
else {
return 0;
else if (result == RUBY_Qfalse) {
rb_raise(rb_eIOTimeoutError, "Timed out waiting for IO to become writable!");
}
return 0;
}
static void

View File

@ -458,10 +458,6 @@ describe "C-API IO function" do
@o.rb_io_maybe_wait(Errno::EINTR::Errno, @w_io, IO::WRITABLE, nil).should == IO::WRITABLE
end
it "returns false if there is no error condition" do
@o.rb_io_maybe_wait(0, @w_io, IO::WRITABLE, nil).should == false
end
it "raises an IOError if the IO is closed" do
@w_io.close
-> { @o.rb_io_maybe_wait(0, @w_io, IO::WRITABLE, nil) }.should raise_error(IOError, "closed stream")
@ -521,6 +517,14 @@ describe "C-API IO function" do
end
end
end
ruby_version_is "3.4" do
describe "rb_io_maybe_wait" do
it "returns nil if there is no error condition" do
@o.rb_io_maybe_wait(0, @w_io, IO::WRITABLE, nil).should == nil
end
end
end
end
describe "rb_fd_fix_cloexec" do