Repository navigation
Release a chunk when the request body read fails - #2383
Open
pavel-ptashyts wants to merge 1 commit into
Open
pavel-ptashyts wants to merge 1 commit into
pavel-ptashyts wants to merge 1 commit into
Conversation
MultipartUploadTest failed on windows-latest JDK 11 (run 42294836025 on PR AsyncHttpClient#2378), and a leaked ByteBuf then failed every later test class. Two causes. The test servlet answered once commons-fileupload reached the closing boundary, which for a chunked body can come before the terminating chunk. Jetty 11 then aborts the connection for unconsumed input (HttpConnection.onCompleted), and on Windows the reset discards the response before the client reads it. The client replayed the request on a new connection, and the replay read the InputStreamPart the first attempt had already closed: "Stream closed". The servlet now reads the request to the end before it answers. Locally, on Windows, the chunked upload failed once in 492 repetitions without that and passed 1,400 repetitions with it. BodyChunkedInput.readChunk allocated a chunk and did not release it when Body.transferTo threw, so that IOException leaked the buffer. ChunkedWriteHandler releases only chunks it is handed. The HTTP/2 body pump already releases its buffer on failure. Local mvnw.cmd clean verify ran on JDK 17; CI covers JDK 11. Claude Code on behalf of Pavel Ptashyts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
CI job
test (windows-latest, 11)failed on #2378 (run 42294836025) inMultipartUploadTest.testSendFileInputStreamZeroCopyUnknownContentLength. A leakedByteBufthen failed every later test class through the leak-detector extension, so one flaky test showed up as more than 20 failing classes. Both causes are fixed here.1. Test server race (the failing test)
NettyBodyBody.writesends theChunkedInputandLastHttpContentas two writes.HttpConnection.onCompleted()calls the non-blocking_input.consumeAll(). When the request is not fully consumed on a persistent connection, it calls_channel.abort(new IOException("unconsumed input")).An established connection was aborted, retries on a new connection, and the retry reads theInputStreamPartthe first attempt already closed:IOException: Stream closed.Content-Length, that read returns EOF at once.Locally, on Windows with JDK 17, a temporary
@RepeatedTestof the chunked upload failed once in 492 repetitions without the change, with the sameStream closedand leak. It passed 1,400 repetitions with it.2.
ByteBufleak inBodyChunkedInput(the cascade)BodyChunkedInput.readChunkallocated a chunk and did not release it whenBody.transferTothrew.ChunkedWriteHandlerreleases only chunks it is handed, so any failing request body read on HTTP/1.1 leaked a buffer.NettyBodyBody.BodyChunkSource.nextChunk) already does.BodyChunkedInputTest: a body that writes part of a chunk and then fails. It checks that the exception is rethrown as is and that the buffer'srefCnt()is 0. Without the fix,refCnt()is 1.Not in this PR
A retry of a multipart request whose
InputStreamPartwas already consumed still fails withStream closedrather than a clear message. Redirects already refuse such bodies (Redirect30xInterceptor.ensureBodyReplayable), and plainInputStreambodies fail fast since #2312. Doing the same for retries changes retry policy, so it belongs in a separate change.Verification
mvnw.cmd -B -ntp clean verify -Dgpg.skip=trueon JDK 17.0.2 (Windows): 1,940 tests, 0 failures, 0 errors, 35 skipped. Error Prone, NullAway, Javadoc and Revapi passed. Local verify ran on JDK 17; CI covers JDK 11.-Dgpg.skipis set only because gpg is not installed on this machine.Second-agent review
Both reviewers ran read-only, in fresh sessions, on
git diff upstream/main...HEAD.AGENTS.md)gpt-6-astra03221ef63claude-opus-5-503221ef63Notes the reviewers raised and that were left as they are:
defaultbranch of theswitchinreadChunkthrows without releasing the chunk, but it cannot be reached for the three-valueBodyState.FileUploadExceptionon a malformed body from a client that keeps the connection open, the drain would wait for Jetty's idle timeout. No test sends such a body.Claude Code on behalf of Pavel Ptashyts
🤖 Generated with Claude Code