diff options
author | Samuel Williams <[email protected]> | 2021-06-20 11:05:15 +1200 |
---|---|---|
committer | Samuel Williams <[email protected]> | 2021-06-22 22:48:57 +1200 |
commit | fcc6fd23ec779a2421154bad441e168e4c6d4194 (patch) | |
tree | 989e3f125c8759854d8a3e8f82ed81b812c163f0 | |
parent | 45e65f302b663b2c6ab69df06d3b6f219c1797b2 (diff) |
Rework `sysread` to use blocking `read_internal_locktmp`.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/4592
-rw-r--r-- | io.c | 18 | ||||
-rw-r--r-- | test/ruby/test_io.rb | 12 |
2 files changed, 15 insertions, 15 deletions
@@ -5349,30 +5349,24 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io) 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 42149ac32a..14592e4d58 100644 --- a/test/ruby/test_io.rb +++ b/test/ruby/test_io.rb @@ -3316,11 +3316,17 @@ __END__ 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) |