Rework sysread
to use blocking read_internal_locktmp
.
This commit is contained in:
parent
45e65f302b
commit
fcc6fd23ec
Notes:
git
2021-06-22 19:49:19 +09:00
18
io.c
18
io.c
@ -5349,30 +5349,24 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io)
|
|||||||
rb_raise(rb_eIOError, "sysread for buffered 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);
|
rb_io_check_closed(fptr);
|
||||||
|
|
||||||
io_setstrbuf(&str, ilen);
|
io_setstrbuf(&str, ilen);
|
||||||
|
iis.th = rb_thread_current();
|
||||||
iis.fd = fptr->fd;
|
iis.fd = fptr->fd;
|
||||||
iis.nonblock = 1; /* for historical reasons, maybe (see above) */
|
iis.nonblock = 0;
|
||||||
iis.buf = RSTRING_PTR(str);
|
iis.buf = RSTRING_PTR(str);
|
||||||
iis.capa = ilen;
|
iis.capa = ilen;
|
||||||
n = read_internal_locktmp(str, &iis);
|
n = read_internal_locktmp(str, &iis);
|
||||||
|
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
rb_sys_fail_path(fptr->pathv);
|
rb_sys_fail_path(fptr->pathv);
|
||||||
}
|
}
|
||||||
|
|
||||||
io_set_read_length(str, n, shrinkable);
|
io_set_read_length(str, n, shrinkable);
|
||||||
|
|
||||||
if (n == 0 && ilen > 0) {
|
if (n == 0 && ilen > 0) {
|
||||||
rb_eof_error();
|
rb_eof_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
|
@ -3316,11 +3316,17 @@ __END__
|
|||||||
data = "a" * 100
|
data = "a" * 100
|
||||||
with_pipe do |r,w|
|
with_pipe do |r,w|
|
||||||
th = Thread.new {r.sysread(100, buf)}
|
th = Thread.new {r.sysread(100, buf)}
|
||||||
|
|
||||||
Thread.pass until th.stop?
|
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)
|
w.write(data)
|
||||||
Thread.pass while th.alive?
|
|
||||||
th.join
|
th.join
|
||||||
end
|
end
|
||||||
assert_equal(data, buf, bug6099)
|
assert_equal(data, buf, bug6099)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user