diff options
author | Samuel Williams <samuel.williams@oriontransfer.co.nz> | 2021-03-30 19:11:17 +1300 |
---|---|---|
committer | Samuel Williams <samuel.williams@oriontransfer.co.nz> | 2021-03-30 23:16:59 +1300 |
commit | a9c5c2d614f30a616970245fef3e7ffc151e2ecf (patch) | |
tree | 7c33e368b99b479cc0cfe01db4d27d453fa96976 | |
parent | 611e711085c7e3984555a79626d025c8b876eced (diff) |
Check errno before invoking scheduler in `rb_io_wait_readable/writable`.
See <https://bugs.ruby-lang.org/issues/17527> for more details.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/4338
-rw-r--r-- | io.c | 66 |
1 files changed, 35 insertions, 31 deletions
@@ -1305,71 +1305,75 @@ rb_io_from_fd(int fd) int rb_io_wait_readable(int f) { + io_fd_check_closed(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); 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) { + io_fd_check_closed(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); 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; } } |