On 06/11/2022 19:35, Thomas Hoffmann (Speed4Trade GmbH) wrote:
Hello Mark,

I found some time for digging into this older topic with the combination http2, 
Firefox, Compression and only partly loaded pages.
I hope I or the topic doesn’t bother you.

Not at all. If there is a Tomcat bug here, I want to get it fixed.

As apache-tomcat-10.0.0-M7 doesn’t show the problem with broken pages in FF 
(jsp page only partly loads) and
it showed up with apache-tomcat-10.0.0-M8, I was taking a look at the changes. 
This was my current approach to this topic.

The change which makes the difference is in Http2UpgradeHandler:
int reserveWindowSize(Stream stream, int reservation, boolean block) throws 
IOException {
...
                 if (!stream.canWrite()) {
                     
stream.doStreamCancel(sm.getString("upgradeHandler.stream.notWritable",
                             stream.getConnectionId(), stream.getIdAsString()), 
Http2Error.STREAM_CLOSED);
                 }

The older version just threw an exception instead of calling doStreamCancel 
when the client is closing the stream:

        if (!stream.canWrite()) {
                         throw new CloseNowException(
                                 
sm.getString("upgradeHandler.stream.notWritable",
                                         stream.getConnectionId(), 
stream.getIdentifier()));
                     }

The method doStreamCancel is setting some properties before throwing also a 
CloseNowException:

     void doStreamCancel(String msg, Http2Error error) throws CloseNowException 
{
         StreamException se = new StreamException(msg, error, getIdAsInt());
         // Prevent the application making further writes
         streamOutputBuffer.closed = true;
         // Prevent Tomcat's error handling trying to write
         coyoteResponse.setError();
         coyoteResponse.setErrorReported();
         // Trigger a reset once control returns to Tomcat
         streamOutputBuffer.reset = se;
         throw new CloseNowException(msg, se);
     }

The line "streamOutputBuffer.closed = true;" seems to be responsible for the 
partly shown pages in FF.
If I comment out this line, no problem shows up with FF, http2 and 
compression="force".

Nice bit of detective work. Setting streamOutputBuffer.closed=true will prevent the application from writing the rest of the resource content which would explain the partial response seen on the client side.

This line seems to have some side effect somewhere else.
Unfortunately, I don’t know the code of Tomcat and http2 protocol.
Can you think about which side effect this line might have (in combination with 
compression / GZipOutputFilter)?
Maybe you have an inspiring idea about the cause or have a hint, where to 
follow the track.

I think this is more symptom rather than root cause. The symptom is visible because of the change to call doStreamCancel() but the question for me is what is triggering this to be called in the first place.

Digging into that a little:

stream.canWrite() needs to return false.

That happens when the Stream is in one of the states that does not permit write. Those states are:
IDLE
RESERVED_LOCAL
HALF_CLOSED_LOCAL
CLOSED_RX
CLOSED_TX
CLOSED_RST_RX
CLOSED_RST_TX

One thing we could do is improve the error message so it logs the current Stream state. That will help narrow down how the Stream got into that state.

I'll get than done for the next set of releases.

Mark

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to