Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=62614
HTTP/2 was not triggering calls to onWritePossible() after isReady() returned false and the window size was subsequently increased

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1837871 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
index 4fdcd2b..c3a0b7d 100644
--- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java
+++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
@@ -34,10 +34,12 @@
 
 import javax.servlet.http.WebConnection;
 
+import org.apache.coyote.ActionCode;
 import org.apache.coyote.Adapter;
 import org.apache.coyote.CloseNowException;
 import org.apache.coyote.ProtocolException;
 import org.apache.coyote.Request;
+import org.apache.coyote.Response;
 import org.apache.coyote.http11.upgrade.InternalHttpUpgradeHandler;
 import org.apache.coyote.http2.HpackDecoder.HeaderEmitter;
 import org.apache.coyote.http2.HpackEncoder.State;
@@ -804,8 +806,23 @@
 
         if (streamsToNotify != null) {
             for (AbstractStream stream : streamsToNotify) {
-                synchronized (stream) {
-                    stream.notifyAll();
+                if (log.isDebugEnabled()) {
+                    log.debug(sm.getString("upgradeHandler.releaseBacklog",
+                            connectionId, stream.getIdentifier()));
+                }
+                Response coyoteResponse = ((Stream) stream).getCoyoteResponse();
+                if (coyoteResponse.getWriteListener() == null) {
+                    // Blocking, so use notify to release StreamOutputBuffer
+                    synchronized (stream) {
+                        stream.notifyAll();
+                    }
+                } else {
+                    // Non-blocking so dispatch
+                    coyoteResponse.action(ActionCode.DISPATCH_WRITE, null);
+                    // Need to explicitly execute dispatches on the
+                    // StreamProcessor as this thread is being processed by an
+                    // UpgradeProcessor which won't see this dispatch
+                    coyoteResponse.action(ActionCode.DISPATCH_EXECUTE, null);
                 }
             }
         }
diff --git a/java/org/apache/coyote/http2/LocalStrings.properties b/java/org/apache/coyote/http2/LocalStrings.properties
index caacb9e..db3e692 100644
--- a/java/org/apache/coyote/http2/LocalStrings.properties
+++ b/java/org/apache/coyote/http2/LocalStrings.properties
@@ -128,6 +128,7 @@
 upgradeHandler.pruneStart=Connection [{0}] Starting pruning of old streams. Limit is [{1}] + 10% and there are currently [{2}] streams.
 upgradeHandler.pruned=Connection [{0}] Pruned completed stream [{1}]
 upgradeHandler.prunedPriority=Connection [{0}] Pruned unused stream [{1}] that may have been part of the priority tree
+upgradeHandler.releaseBacklog=Connection [{0}], Stream [{1}] released from backlog
 upgradeHandler.rst.debug=Connection [{0}], Stream [{1}], Error [{2}], Message [{3}],  RST (closing stream)
 upgradeHandler.sendPrefaceFail=Connection [{0}], Failed to send preface to client
 upgradeHandler.socketCloseFailed=Error closing socket
diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java
index 36c7473..a33bd3b 100644
--- a/java/org/apache/coyote/http2/Stream.java
+++ b/java/org/apache/coyote/http2/Stream.java
@@ -196,7 +196,17 @@
         boolean notify = getWindowSize() < 1;
         super.incrementWindowSize(windowSizeIncrement);
         if (notify && getWindowSize() > 0) {
-            notifyAll();
+            if (coyoteResponse.getWriteListener() == null) {
+                // Blocking, so use notify to release StreamOutputBuffer
+                notifyAll();
+            } else {
+                // Non-blocking so dispatch
+                coyoteResponse.action(ActionCode.DISPATCH_WRITE, null);
+                // Need to explicitly execute dispatches on the StreamProcessor
+                // as this thread is being processed by an UpgradeProcessor
+                // which won't see this dispatch
+                coyoteResponse.action(ActionCode.DISPATCH_EXECUTE, null);
+            }
         }
     }