https://bz.apache.org/bugzilla/show_bug.cgi?id=70313

            Bug ID: 70313
           Summary: HTTP/2 async response is never completed if complete()
                    is called while buffered output is waiting for window
           Product: Tomcat 11
           Version: 11.0.27
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Connectors
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: -------

An asynchronous servlet that writes its response with a WriteListener and calls
complete() as soon as isReady() returns true after the last write never
finishes the response if, at that point, buffered output is waiting for
connection flow control window. The client receives the data that fitted in the
window and the stream then stays open until the async timeout.

To reproduce, use HTTP/2 with a response that is 8193 to 16384 bytes larger
than the connection window, written like this:

while (out.isReady()) {
    if (written >= size) {
        asyncContext.complete();
        return;
    }
    out.write(...);
}

Let the client use the whole connection window and then send a WINDOW_UPDATE.
The remaining bytes are never sent.

The cause is that complete() clears the write listener
(AsyncStateMachine.clearNonBlockingListeners()). While completing, the
processor writes the buffered output without blocking
(AsyncStateMachine.asyncPostProcess(), COMPLETING state) and registers a
non-blocking wait for the window. When the window is increased,
WindowAllocationManager.notify() chooses between signalling a blocked thread
and dispatching a write by testing response.getWriteListener() == null. The
listener is already null, so it signals a thread that does not exist and
nothing is dispatched.

I can reproduce this on main and 11.0.x. 10.1.x is not affected. A test that
fails without the fix and passes with it, and a fix, will follow in a pull
request.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to