mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Reduce chance to receive EBADF when closing an IO from another thread.
This commit is contained in:
parent
587f501c7c
commit
3a8cadcf8f
Notes:
git
2021-08-08 19:12:39 +09:00
1 changed files with 27 additions and 19 deletions
46
io.c
46
io.c
|
@ -1422,6 +1422,13 @@ rb_thread_fd_writable(int fd)
|
||||||
|
|
||||||
VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout)
|
VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout)
|
||||||
{
|
{
|
||||||
|
// fptr->fd can be set to -1 at any time by another thread when the GVL is
|
||||||
|
// released. Many code, e.g. `io_bufread` didn't check this correctly and
|
||||||
|
// instead relies on `read(-1) -> -1` which causes this code path. We then
|
||||||
|
// check here whether the IO was in fact closed. Probably it's better to
|
||||||
|
// check that `fptr->fd != -1` before using it in syscall.
|
||||||
|
rb_io_check_closed(RFILE(io)->fptr);
|
||||||
|
|
||||||
switch (error) {
|
switch (error) {
|
||||||
// In old Linux, several special files under /proc and /sys don't handle
|
// 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.
|
// select properly. Thus we need avoid to call if don't use O_NONBLOCK.
|
||||||
|
@ -2646,31 +2653,32 @@ io_bufread(char *ptr, long len, rb_io_t *fptr)
|
||||||
long c;
|
long c;
|
||||||
|
|
||||||
if (READ_DATA_PENDING(fptr) == 0) {
|
if (READ_DATA_PENDING(fptr) == 0) {
|
||||||
while (n > 0) {
|
while (n > 0) {
|
||||||
again:
|
again:
|
||||||
c = rb_read_internal(fptr->fd, ptr+offset, n);
|
rb_io_check_closed(fptr);
|
||||||
if (c == 0) break;
|
c = rb_read_internal(fptr->fd, ptr+offset, n);
|
||||||
if (c < 0) {
|
if (c == 0) break;
|
||||||
|
if (c < 0) {
|
||||||
if (fptr_wait_readable(fptr))
|
if (fptr_wait_readable(fptr))
|
||||||
goto again;
|
goto again;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
offset += c;
|
offset += c;
|
||||||
if ((n -= c) <= 0) break;
|
if ((n -= c) <= 0) break;
|
||||||
}
|
}
|
||||||
return len - n;
|
return len - n;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (n > 0) {
|
while (n > 0) {
|
||||||
c = read_buffered_data(ptr+offset, n, fptr);
|
c = read_buffered_data(ptr+offset, n, fptr);
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
offset += c;
|
offset += c;
|
||||||
if ((n -= c) <= 0) break;
|
if ((n -= c) <= 0) break;
|
||||||
}
|
}
|
||||||
rb_io_check_closed(fptr);
|
rb_io_check_closed(fptr);
|
||||||
if (io_fillbuf(fptr) < 0) {
|
if (io_fillbuf(fptr) < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return len - n;
|
return len - n;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue