diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-10-23 05:28:12 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-10-23 05:28:12 +0000 |
commit | 08524bc59477176b270a0249784af4e37ab3fed9 (patch) | |
tree | 5415979281288379ef68db9efe01756d7edb5594 | |
parent | 71a7ef31d7d6343468db164804340920e17c2705 (diff) | |
download | ruby-08524bc59477176b270a0249784af4e37ab3fed9.tar.gz |
io.c: fix infinite retry
* io.c (io_binwritev): fix infinite retry when flushing buffered
data. [Feature #9323]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60373 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | io.c | 26 | ||||
-rw-r--r-- | test/ruby/test_io.rb | 10 |
2 files changed, 23 insertions, 13 deletions
@@ -1534,7 +1534,7 @@ io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr) } else { iov++; - iovcnt--; + if (!--iovcnt) return 0; } retry: @@ -1557,25 +1557,25 @@ io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr) fptr->wbuf.len -= r; } else { + written_len -= fptr->wbuf.len; fptr->wbuf.off = 0; fptr->wbuf.len = 0; } } - if (written_len == total) return written_len; + if (written_len == total) return total; - for (i = 0; i < iovcnt; i++) { - if (r > (ssize_t)iov[i].iov_len) { - r -= iov[i].iov_len; - iov[i].iov_len = 0; - } - else { - iov[i].iov_base = (char *)iov[i].iov_base + r; - iov[i].iov_len -= r; - break; - } + while (r >= (ssize_t)iov->iov_len) { + /* iovcnt > 0 */ + r -= iov->iov_len; + iov->iov_len = 0; + iov++; + if (!--iovcnt) return total; + /* defensive check: written_len should == total */ } + iov->iov_base = (char *)iov->iov_base + r; + iov->iov_len -= r; - errno = EAGAIN; + errno = EAGAIN; } if (rb_io_wait_writable(fptr->fd)) { rb_io_check_closed(fptr); diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb index 1fa9dbb443..c7de83784b 100644 --- a/test/ruby/test_io.rb +++ b/test/ruby/test_io.rb @@ -1236,6 +1236,16 @@ class TestIO < Test::Unit::TestCase open(file, "rb") do |r| assert_equal([line, line, "\n"], r.readlines) end + + line = "x"*99+"\n" + open(file, "wb") do |w| + w.write(line*81) # 8100 bytes + assert_equal(100, w.write("a"*99, "\n")) + end + open(file, "rb") do |r| + 81.times {assert_equal(line, r.gets)} + assert_equal("a"*99+"\n", r.gets) + end end end |