summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--io.c10
-rw-r--r--test/ruby/test_io.rb26
-rw-r--r--version.h2
3 files changed, 35 insertions, 3 deletions
diff --git a/io.c b/io.c
index 7f23656049..b4b262b6ac 100644
--- a/io.c
+++ b/io.c
@@ -1156,8 +1156,14 @@ io_internal_wait(VALUE thread, rb_io_t *fptr, int error, int events, struct time
return -1;
}
- errno = error;
- return -1;
+ // If there was an error BEFORE we started waiting, return it:
+ if (error) {
+ errno = error;
+ return -1;
+ } else {
+ // Otherwise, whatever error was generated by `nogvl_wait_for` is the one we want:
+ return ready;
+ }
}
static VALUE
diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb
index 16de2e8a76..760279ca3d 100644
--- a/test/ruby/test_io.rb
+++ b/test/ruby/test_io.rb
@@ -4297,4 +4297,30 @@ __END__
end
end
end
+
+ def test_blocking_timeout
+ assert_separately([], <<~'RUBY')
+ IO.pipe do |r, w|
+ trap(:INT) do
+ w.puts "INT"
+ end
+
+ main = Thread.current
+ thread = Thread.new do
+ # Wait until the main thread has entered `$stdin.gets`:
+ Thread.pass until main.status == 'sleep'
+
+ # Cause an interrupt while handling `$stdin.gets`:
+ Process.kill :INT, $$
+ end
+
+ r.timeout = 1
+ assert_equal("INT", r.gets.chomp)
+ rescue IO::TimeoutError
+ # Ignore - some platforms don't support interrupting `gets`.
+ ensure
+ thread&.join
+ end
+ RUBY
+ end
end
diff --git a/version.h b/version.h
index b9f9eee68d..31b5671956 100644
--- a/version.h
+++ b/version.h
@@ -11,7 +11,7 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 7
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
-#define RUBY_PATCHLEVEL 138
+#define RUBY_PATCHLEVEL 139
#include "ruby/version.h"
#include "ruby/internal/abi.h"