diff options
author | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-11-22 22:44:06 +0000 |
---|---|---|
committer | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-11-22 22:44:06 +0000 |
commit | 8a233ea67b20910c6fc3429d6c30c628c1650255 (patch) | |
tree | c35d07a1b344a18f3db240d142953824b3f4682f | |
parent | fc0a92aba0704a66c2239f59e04131f66c379e34 (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
-rw-r--r-- | io.c | 16 |
1 files changed, 13 insertions, 3 deletions
@@ -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)) |