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);
+ }
}
}