ruby-changes:48258
From: nobu <ko1@a...>
Date: Mon, 23 Oct 2017 14:28:17 +0900 (JST)
Subject: [ruby-changes:48258] nobu:r60373 (trunk): io.c: fix infinite retry
nobu 2017-10-23 14:28:12 +0900 (Mon, 23 Oct 2017) New Revision: 60373 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=60373 Log: io.c: fix infinite retry * io.c (io_binwritev): fix infinite retry when flushing buffered data. [Feature #9323] Modified files: trunk/io.c trunk/test/ruby/test_io.rb Index: test/ruby/test_io.rb =================================================================== --- test/ruby/test_io.rb (revision 60372) +++ test/ruby/test_io.rb (revision 60373) @@ -1236,6 +1236,16 @@ class TestIO < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_io.rb#L1236 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 Index: io.c =================================================================== --- io.c (revision 60372) +++ io.c (revision 60373) @@ -1534,7 +1534,7 @@ io_binwritev(struct iovec *iov, int iovc https://github.com/ruby/ruby/blob/trunk/io.c#L1534 } else { iov++; - iovcnt--; + if (!--iovcnt) return 0; } retry: @@ -1557,25 +1557,25 @@ io_binwritev(struct iovec *iov, int iovc https://github.com/ruby/ruby/blob/trunk/io.c#L1557 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); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/