When a client POSTs data using chunked encoding, and a network packet ends immediately after the chunk header, but before the chunk body, the AbstractListenerReadPublisher hangs under Tomcat, especially in constrained environments.
When the packet that ends with the chunk header is received, Tomcat calls ReadListener::onDataAvailable().
The ServletServerHttpRequest.RequestBodyPublisher calls ServletOutputStream::isReady(), which returns true.
The RequestBodyPublisher tries to read data, and Tomcat processes the chunk header (so data has been read from the network).
However, there is no actual content available (yet), so Tomcat returns 0 bytes.
The RequestBodyPublisher sees no data has been read, and switches state to DEMAND.
The RequestBodyPublisher doesn't call isReady() because it assumes the read terminated, as isReady() returned false.
No call to isReady() means the socket is not registered for read and everything hangs.
Special thanks to @markt-asf for investigating the issue, and providing the description above.
When a client POSTs data using chunked encoding, and a network packet ends immediately after the chunk header, but before the chunk body, the
AbstractListenerReadPublisherhangs under Tomcat, especially in constrained environments.When the packet that ends with the chunk header is received, Tomcat calls
ReadListener::onDataAvailable().The
ServletServerHttpRequest.RequestBodyPublishercallsServletOutputStream::isReady(), which returnstrue.The
RequestBodyPublishertries to read data, and Tomcat processes the chunk header (so data has been read from the network).However, there is no actual content available (yet), so Tomcat returns 0 bytes.
The
RequestBodyPublishersees no data has been read, and switches state to DEMAND.The
RequestBodyPublisherdoesn't callisReady()because it assumes the read terminated, asisReady()returnedfalse.No call to
isReady()means the socket is not registered for read and everything hangs.Special thanks to @markt-asf for investigating the issue, and providing the description above.