1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Check errno before invoking scheduler in rb_io_wait_readable/writable.

See <https://bugs.ruby-lang.org/issues/17527> for more details.
This commit is contained in:
Samuel Williams 2021-03-30 19:11:17 +13:00
parent 611e711085
commit a9c5c2d614
Notes: git 2021-03-30 19:17:26 +09:00

70
io.c
View file

@ -1305,71 +1305,75 @@ rb_io_from_fd(int fd)
int
rb_io_wait_readable(int f)
{
VALUE scheduler = rb_fiber_scheduler_current();
if (scheduler != Qnil) {
return RTEST(
rb_fiber_scheduler_io_wait_readable(scheduler, rb_io_from_fd(f))
);
}
io_fd_check_closed(f);
VALUE scheduler = rb_fiber_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_fiber_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_fiber_scheduler_current();
if (scheduler != Qnil) {
return RTEST(
rb_fiber_scheduler_io_wait_writable(scheduler, rb_io_from_fd(f))
);
}
io_fd_check_closed(f);
VALUE scheduler = rb_fiber_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_fiber_scheduler_io_wait_writable(scheduler, rb_io_from_fd(f))
);
} else {
rb_thread_fd_writable(f);
}
return TRUE;
default:
return FALSE;
return FALSE;
}
}