summaryrefslogtreecommitdiff
path: root/io.c
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-11-22 22:44:06 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-11-22 22:44:06 +0000
commit8a233ea67b20910c6fc3429d6c30c628c1650255 (patch)
treec35d07a1b344a18f3db240d142953824b3f4682f /io.c
parentfc0a92aba0704a66c2239f59e04131f66c379e34 (diff)
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
Diffstat (limited to 'io.c')
-rw-r--r--io.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/io.c b/io.c
index 0fe0d7a4b2..9ebf62d69d 100644
--- a/io.c
+++ b/io.c
@@ -1997,6 +1997,16 @@ rb_io_rewind(VALUE io)
}
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)
{
ssize_t r;
@@ -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))