ruby-changes:66552
From: Samuel <ko1@a...>
Date: Tue, 22 Jun 2021 19:49:19 +0900 (JST)
Subject: [ruby-changes:66552] fcc6fd23ec (master): Rework `sysread` to use blocking `read_internal_locktmp`.
https://git.ruby-lang.org/ruby.git/commit/?id=fcc6fd23ec From fcc6fd23ec779a2421154bad441e168e4c6d4194 Mon Sep 17 00:00:00 2001 From: Samuel Williams <samuel.williams@o...> Date: Sun, 20 Jun 2021 11:05:15 +1200 Subject: Rework `sysread` to use blocking `read_internal_locktmp`. --- io.c | 18 ++++++------------ test/ruby/test_io.rb | 12 +++++++++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/io.c b/io.c index 7db0560..7033fe6 100644 --- a/io.c +++ b/io.c @@ -5349,30 +5349,24 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io) https://github.com/ruby/ruby/blob/trunk/io.c#L5349 rb_raise(rb_eIOError, "sysread for buffered IO"); } - /* - * FIXME: removing rb_thread_wait_fd() here changes sysread semantics - * on non-blocking IOs. However, it's still currently possible - * for sysread to raise Errno::EAGAIN if another thread read()s - * the IO after we return from rb_thread_wait_fd() but before - * we call read() - */ - rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil); - rb_io_check_closed(fptr); io_setstrbuf(&str, ilen); + iis.th = rb_thread_current(); iis.fd = fptr->fd; - iis.nonblock = 1; /* for historical reasons, maybe (see above) */ + iis.nonblock = 0; iis.buf = RSTRING_PTR(str); iis.capa = ilen; n = read_internal_locktmp(str, &iis); if (n < 0) { - rb_sys_fail_path(fptr->pathv); + rb_sys_fail_path(fptr->pathv); } + io_set_read_length(str, n, shrinkable); + if (n == 0 && ilen > 0) { - rb_eof_error(); + rb_eof_error(); } return str; diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb index 42149ac..14592e4 100644 --- a/test/ruby/test_io.rb +++ b/test/ruby/test_io.rb @@ -3316,11 +3316,17 @@ __END__ https://github.com/ruby/ruby/blob/trunk/test/ruby/test_io.rb#L3316 data = "a" * 100 with_pipe do |r,w| th = Thread.new {r.sysread(100, buf)} + Thread.pass until th.stop? - buf.replace("") - assert_empty(buf, bug6099) + + assert_equal 100, buf.bytesize + + msg = /can't modify string; temporarily locked/ + assert_raise_with_message(RuntimeError, msg) do + buf.replace("") + end + assert_predicate(th, :alive?) w.write(data) - Thread.pass while th.alive? th.join end assert_equal(data, buf, bug6099) -- cgit v1.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/