This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit d57e1ca2fc25c9234caed8d74ec741585ff59256 Author: Mark Thomas <ma...@apache.org> AuthorDate: Fri Sep 13 16:37:55 2019 +0100 Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63682 HTTP/2 hang Fix a potential hang when using the asynchronous Servlet API to write the response body and the stream and/or connection window reaches 0 bytes in size. --- java/org/apache/coyote/http2/Stream.java | 12 +++++++++--- .../apache/coyote/http2/WindowAllocationManager.java | 17 +++++++++++++++++ webapps/docs/changelog.xml | 5 +++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java index a25edfe..6b6eb93 100644 --- a/java/org/apache/coyote/http2/Stream.java +++ b/java/org/apache/coyote/http2/Stream.java @@ -937,12 +937,18 @@ public class Stream extends AbstractStream implements HeaderEmitter { } synchronized boolean isReady() { - if (getWindowSize() > 0 && handler.getWindowSize() > 0 && !dataLeft) { - return true; - } else { + // Bug 63682 + // Only want to return false if the window size is zero AND we are + // already waiting for an allocation. + if (getWindowSize() > 0 && allocationManager.isWaitingForStream() || + handler.getWindowSize() > 0 && allocationManager.isWaitingForConnection() || + dataLeft) { writeInterest = true; return false; + } else { + return true; } + } synchronized boolean isRegisteredForWrite() { diff --git a/java/org/apache/coyote/http2/WindowAllocationManager.java b/java/org/apache/coyote/http2/WindowAllocationManager.java index da7aebe..f286430 100644 --- a/java/org/apache/coyote/http2/WindowAllocationManager.java +++ b/java/org/apache/coyote/http2/WindowAllocationManager.java @@ -119,6 +119,23 @@ class WindowAllocationManager { } + boolean isWaitingForStream() { + return isWaitingFor(STREAM); + } + + + boolean isWaitingForConnection() { + return isWaitingFor(CONNECTION); + } + + + private boolean isWaitingFor(int waitTarget) { + synchronized (stream) { + return (waitingFor & waitTarget) > 0; + } + } + + private void waitFor(int waitTarget, long timeout) throws InterruptedException { synchronized (stream) { if (waitingFor != NONE) { diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index a0e538e..75c640c 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -62,6 +62,11 @@ <subsection name="Coyote"> <changelog> <fix> + <bug>63682</bug>: Fix a potential hang when using the asynchronous + Servlet API to write the response body and the stream and/or connection + window reaches 0 bytes in size. (markt) + </fix> + <fix> <bug>63690</bug>: Use the average of the current and previous sizes when calculating overhead for HTTP/2 <code>DATA</code> and <code>WINDOW_UPDATE</code> frames to avoid false positives as a result --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org