[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]