mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
merge revision(s) 611e711085c7e3984555a79626d025c8b876eced,a9c5c2d614f30a616970245fef3e7ffc151e2ecf: [Backport #17527]
Test incorrect behaviour of `rb_io_wait_readable/writable`. --- test/fiber/test_io.rb | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) Check errno before invoking scheduler in `rb_io_wait_readable/writable`. See <https://bugs.ruby-lang.org/issues/17527> for more details. --- io.c | 66 +++++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 35 insertions(+), 31 deletions(-)
This commit is contained in:
parent
5a9b5b8e95
commit
13f93ad16d
3 changed files with 74 additions and 33 deletions
68
io.c
68
io.c
|
@ -1306,71 +1306,77 @@ rb_io_from_fd(int fd)
|
|||
int
|
||||
rb_io_wait_readable(int f)
|
||||
{
|
||||
VALUE scheduler = rb_scheduler_current();
|
||||
if (scheduler != Qnil) {
|
||||
return RTEST(
|
||||
rb_scheduler_io_wait_readable(scheduler, rb_io_from_fd(f))
|
||||
);
|
||||
}
|
||||
VALUE scheduler;
|
||||
|
||||
io_fd_check_closed(f);
|
||||
|
||||
scheduler = rb_scheduler_current();
|
||||
switch (errno) {
|
||||
case EINTR:
|
||||
#if defined(ERESTART)
|
||||
case ERESTART:
|
||||
#endif
|
||||
rb_thread_check_ints();
|
||||
return TRUE;
|
||||
rb_thread_check_ints();
|
||||
return TRUE;
|
||||
|
||||
case EAGAIN:
|
||||
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
|
||||
case EWOULDBLOCK:
|
||||
#endif
|
||||
rb_thread_wait_fd(f);
|
||||
return TRUE;
|
||||
if (scheduler != Qnil) {
|
||||
return RTEST(
|
||||
rb_scheduler_io_wait_readable(scheduler, rb_io_from_fd(f))
|
||||
);
|
||||
} else {
|
||||
rb_thread_wait_fd(f);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
rb_io_wait_writable(int f)
|
||||
{
|
||||
VALUE scheduler = rb_scheduler_current();
|
||||
if (scheduler != Qnil) {
|
||||
return RTEST(
|
||||
rb_scheduler_io_wait_writable(scheduler, rb_io_from_fd(f))
|
||||
);
|
||||
}
|
||||
VALUE scheduler;
|
||||
|
||||
io_fd_check_closed(f);
|
||||
|
||||
scheduler = rb_scheduler_current();
|
||||
switch (errno) {
|
||||
case EINTR:
|
||||
#if defined(ERESTART)
|
||||
case ERESTART:
|
||||
#endif
|
||||
/*
|
||||
* In old Linux, several special files under /proc and /sys don't handle
|
||||
* select properly. Thus we need avoid to call if don't use O_NONBLOCK.
|
||||
* Otherwise, we face nasty hang up. Sigh.
|
||||
* e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
|
||||
* http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
|
||||
* In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
|
||||
* Then rb_thread_check_ints() is enough.
|
||||
*/
|
||||
rb_thread_check_ints();
|
||||
return TRUE;
|
||||
/*
|
||||
* In old Linux, several special files under /proc and /sys don't handle
|
||||
* select properly. Thus we need avoid to call if don't use O_NONBLOCK.
|
||||
* Otherwise, we face nasty hang up. Sigh.
|
||||
* e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
|
||||
* http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
|
||||
* In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
|
||||
* Then rb_thread_check_ints() is enough.
|
||||
*/
|
||||
rb_thread_check_ints();
|
||||
return TRUE;
|
||||
|
||||
case EAGAIN:
|
||||
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
|
||||
case EWOULDBLOCK:
|
||||
#endif
|
||||
rb_thread_fd_writable(f);
|
||||
return TRUE;
|
||||
if (scheduler != Qnil) {
|
||||
return RTEST(
|
||||
rb_scheduler_io_wait_writable(scheduler, rb_io_from_fd(f))
|
||||
);
|
||||
} else {
|
||||
rb_thread_fd_writable(f);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,4 +62,39 @@ class TestFiberIO < Test::Unit::TestCase
|
|||
end
|
||||
end.each(&:join)
|
||||
end
|
||||
|
||||
def test_epipe_on_read
|
||||
skip "UNIXSocket is not defined!" unless defined?(UNIXSocket)
|
||||
|
||||
i, o = UNIXSocket.pair
|
||||
|
||||
unless i.nonblock? && o.nonblock?
|
||||
i.close
|
||||
o.close
|
||||
skip "I/O is not non-blocking!"
|
||||
end
|
||||
|
||||
error = nil
|
||||
|
||||
thread = Thread.new do
|
||||
scheduler = Scheduler.new
|
||||
Fiber.set_scheduler scheduler
|
||||
|
||||
Fiber.schedule do
|
||||
begin
|
||||
i.close
|
||||
o.write(MESSAGE)
|
||||
rescue => error
|
||||
# Saved into error.
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
thread.join
|
||||
|
||||
i.close
|
||||
o.close
|
||||
|
||||
assert_kind_of Errno::EPIPE, error
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,11 +12,11 @@
|
|||
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
|
||||
#define RUBY_VERSION_TEENY 2
|
||||
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
|
||||
#define RUBY_PATCHLEVEL 71
|
||||
#define RUBY_PATCHLEVEL 72
|
||||
|
||||
#define RUBY_RELEASE_YEAR 2021
|
||||
#define RUBY_RELEASE_MONTH 4
|
||||
#define RUBY_RELEASE_DAY 18
|
||||
#define RUBY_RELEASE_DAY 24
|
||||
|
||||
#include "ruby/version.h"
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue