Skip to content

Switch from the CRT pull-based HttpRequestBodyStream model to the#6959

Open
zoewangg wants to merge 1 commit into
masterfrom
zoewang/crtWriteStream
Open

Switch from the CRT pull-based HttpRequestBodyStream model to the#6959
zoewangg wants to merge 1 commit into
masterfrom
zoewang/crtWriteStream

Conversation

@zoewangg
Copy link
Copy Markdown
Contributor

Motivation and Context

AwsCrtHttpClient can potentially deadlock when the request body InputStream blocks on the CRT event loop thread. This can occur when a blocking stream (e.g., a BufferedInputStream wrapping a ResponseInputStream) is used as a request body and the read depends on the same event loop thread to deliver data.

CrtRequestInputStreamAdapter.sendRequestBody() is invoked on the CRT event loop thread and calls InputStream.read(), which may block indefinitely. The CRT event loop must never block.

Note that this applies to CRT sync HTTP client only and a follow up PR will be created to update async HTTP client

Modifications

  • Switch from the CRT pull-based HttpRequestBodyStream.sendRequestBody() model to the push-based HttpStreamBase.writeData() API. The caller thread now writes the request body instead of the event loop thread.
  • CrtRequestExecutor.execute() passes useManualDataWrites=true via acquireStream when the request has a body. Returns an ExecutionResult exposing both
    the stream future and response future.
  • AwsCrtHttpClient.CrtHttpRequest.call() waits for stream acquisition, writes the body from the caller thread via stream.writeData(), then waits for the
    response.
  • Remove CrtRequestInputStreamAdapter (no longer used).
  • Bump aws-crt dependency for writeData and acquireStream(request, handler, useManualDataWrites) APIs.

Testing

  • All 191 existing unit tests in http-clients/aws-crt-client pass.
  • S3 integration test confirms the deadlock scenario no longer reproduces.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)

Checklist

  • I have read the CONTRIBUTING document
  • Local run of mvn install succeeds
  • My code follows the code style of this project
  • My change requires a change to the Javadoc documentation
  • I have updated the Javadoc documentation accordingly
  • I have added tests to cover my changes
  • All new and existing tests passed
  • I have added a changelog entry. Adding a new entry must be accomplished by running the scripts/new-change script and following the instructions. Commit
    the new file created by the script in .changes/next-release with your changes.
  • My change is to implement 1.11 parity feature and I have updated
    LaunchChangelog

License

  • I confirm that this pull request can be released under the Apache 2 license

   push-based HttpStreamBase.writeData() API to avoid potential deadlock issue when request body InputStream blocks.
@zoewangg zoewangg requested a review from a team as a code owner May 12, 2026 16:55
Comment thread pom.xml
<commons-codec.verion>1.17.1</commons-codec.verion>
<jmh.version>1.37</jmh.version>
<awscrt.version>0.45.3</awscrt.version>
<awscrt.version>1.0.0-SNAPSHOT</awscrt.version>
Copy link
Copy Markdown
Contributor Author

@zoewangg zoewangg May 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pending on awslabs/aws-crt-java@main...write-stream to be merged

Comment on lines +182 to +185
while ((read = inputStream.read(buf, 0, buf.length)) >= 0) {
byte[] chunk = read == buf.length ? buf : Arrays.copyOf(buf, read);
CompletableFutureUtils.joinInterruptibly(stream.writeData(chunk, false));
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when the input stream has no data available, do we just keep looping until we find data? Seems like we will end up with hot looping and wasting CPU loops for this case.

And, a bit optimization, when there is no data, it will be better to skip invoking the writeData, so that less work to be done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants