io.c: revalidate fptr->fd after rb_io_wait_readable
fptr->fd may become -1 while GVL is released in rb_wait_for_single_fd, so we must check it after reacquiring GVL. This should avoid EBADF errors exposed by making pipes non-blocking by default: http://ci.rvm.jp/results/trunk-test@ruby-sky3/1473710 [Bug #14968] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65931 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
fc0a92aba0
commit
8a233ea67b
16
io.c
16
io.c
@ -1996,6 +1996,16 @@ rb_io_rewind(VALUE io)
|
||||
return INT2FIX(0);
|
||||
}
|
||||
|
||||
static int
|
||||
fptr_wait_readable(rb_io_t *fptr)
|
||||
{
|
||||
int ret = rb_io_wait_readable(fptr->fd);
|
||||
|
||||
if (ret)
|
||||
rb_io_check_closed(fptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
io_fillbuf(rb_io_t *fptr)
|
||||
{
|
||||
@ -2016,7 +2026,7 @@ io_fillbuf(rb_io_t *fptr)
|
||||
r = rb_read_internal(fptr->fd, fptr->rbuf.ptr, fptr->rbuf.capa);
|
||||
}
|
||||
if (r < 0) {
|
||||
if (rb_io_wait_readable(fptr->fd))
|
||||
if (fptr_wait_readable(fptr))
|
||||
goto retry;
|
||||
{
|
||||
int e = errno;
|
||||
@ -2363,7 +2373,7 @@ io_bufread(char *ptr, long len, rb_io_t *fptr)
|
||||
c = rb_read_internal(fptr->fd, ptr+offset, n);
|
||||
if (c == 0) break;
|
||||
if (c < 0) {
|
||||
if (rb_io_wait_readable(fptr->fd))
|
||||
if (fptr_wait_readable(fptr))
|
||||
goto again;
|
||||
return -1;
|
||||
}
|
||||
@ -2788,7 +2798,7 @@ io_getpartial(int argc, VALUE *argv, VALUE io, VALUE opts, int nonblock)
|
||||
n = arg.len;
|
||||
if (n < 0) {
|
||||
int e = errno;
|
||||
if (!nonblock && rb_io_wait_readable(fptr->fd))
|
||||
if (!nonblock && fptr_wait_readable(fptr))
|
||||
goto again;
|
||||
if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) {
|
||||
if (no_exception_p(opts))
|
||||
|
Loading…
x
Reference in New Issue
Block a user