You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2018/11/26 14:24:45 UTC

svn commit: r1847474 - /tomcat/trunk/java/org/apache/coyote/http2/Stream.java

Author: markt
Date: Mon Nov 26 14:24:45 2018
New Revision: 1847474

URL: http://svn.apache.org/viewvc?rev=1847474&view=rev
Log:
Fix (hopefully) intermittent HTTP/2 test failures with async I/O.

Modified:
    tomcat/trunk/java/org/apache/coyote/http2/Stream.java

Modified: tomcat/trunk/java/org/apache/coyote/http2/Stream.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Stream.java?rev=1847474&r1=1847473&r2=1847474&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Stream.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Stream.java Mon Nov 26 14:24:45 2018
@@ -717,6 +717,10 @@ class Stream extends AbstractStream impl
 
         private final ByteBuffer buffer = ByteBuffer.allocate(8 * 1024);
         private final WriteBuffer writeBuffer = new WriteBuffer(32 * 1024);
+        // Flag that indicates that data was left over on a previous
+        // non-blocking write. Once set, this flag stays set until all the data
+        // has been written.
+        private boolean dataLeft;
         private volatile long written = 0;
         private int streamReservation = 0;
         private volatile boolean closed = false;
@@ -747,6 +751,7 @@ class Stream extends AbstractStream impl
                         // is full
                         if (flush(true, coyoteResponse.getWriteListener() == null)) {
                             writeBuffer.add(chunk);
+                            dataLeft = true;
                             break;
                         }
                     }
@@ -767,17 +772,20 @@ class Stream extends AbstractStream impl
              * Too many calls and the end of stream message is sent too soon and
              * trailer headers are not sent.
              */
-            boolean dataLeft = buffer.position() > 0;
+            boolean dataInBuffer = buffer.position() > 0;
             boolean flushed = false;
 
-            if (dataLeft) {
-                dataLeft = flush(false, block);
+            if (dataInBuffer) {
+                dataInBuffer = flush(false, block);
                 flushed = true;
             }
 
-            if (!dataLeft) {
+            if (!dataInBuffer) {
                 if (writeBuffer.isEmpty()) {
-                    if (!flushed) {
+                    // Both buffer and writeBuffer are empty.
+                    if (flushed) {
+                        dataLeft = false;
+                    } else {
                         dataLeft = flush(false, block);
                     }
                 } else {
@@ -811,10 +819,10 @@ class Stream extends AbstractStream impl
                 if (streamReservation == 0) {
                     streamReservation  = reserveWindowSize(left, block);
                     if (streamReservation == 0) {
-                        // Must be non-blocking. Unwritten non-blocking data
-                        // must put in writeBuffer else isReady() logic breaks
-                        writeBuffer.add(buffer);
-                        buffer.clear();
+                        // Must be non-blocking.
+                        // Note: Can't add to the writeBuffer here as the write
+                        // may originate from the writeBuffer.
+                        buffer.compact();
                         return true;
                     }
                 }
@@ -822,10 +830,10 @@ class Stream extends AbstractStream impl
                     int connectionReservation =
                                 handler.reserveWindowSize(Stream.this, streamReservation, block);
                     if (connectionReservation == 0) {
-                        // Must be non-blocking. Unwritten non-blocking data
-                        // must put in writeBuffer else isReady() logic breaks
-                        writeBuffer.add(buffer);
-                        buffer.clear();
+                        // Must be non-blocking.
+                        // Note: Can't add to the writeBuffer here as the write
+                        // may originate from the writeBuffer.
+                        buffer.compact();
                         return true;
                     }
                     // Do the write
@@ -841,7 +849,7 @@ class Stream extends AbstractStream impl
         }
 
         final synchronized boolean isReady() {
-            if (getWindowSize() > 0 && handler.getWindowSize() > 0 && writeBuffer.isEmpty()) {
+            if (getWindowSize() > 0 && handler.getWindowSize() > 0 && !dataLeft) {
                 return true;
             } else {
                 return false;



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org