-
Notifications
You must be signed in to change notification settings - Fork 573
Fix HTTP streaming Abort() not canceling response reception and add unit tests #5886
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: mconnew <8648390+mconnew@users.noreply.github.com>
Co-authored-by: mconnew <8648390+mconnew@users.noreply.github.com>
Co-authored-by: mconnew <8648390+mconnew@users.noreply.github.com>
|
@copilot, you didn't make any changes to address the problem described in the issue. You only wrote the test that was described in the additional instructions. |
Co-authored-by: mconnew <8648390+mconnew@users.noreply.github.com>
Co-authored-by: mconnew <8648390+mconnew@users.noreply.github.com>
Co-authored-by: mconnew <8648390+mconnew@users.noreply.github.com>
You're absolutely right - I misunderstood the original instructions. I only created the unit test but didn't implement the actual fix for the issue. I'm now implementing the fix to propagate Abort() to the response stream reading operations. |
- Added CancellationToken parameter to HttpResponseMessageHelper constructor - Created GetCombinedCancellationTokenAsync helper to combine timeout and abort tokens - Updated all stream reading operations to use combined cancellation token - Pass _httpSendCts.Token from HttpClientChannelAsyncRequest to enable abort during response reception Co-authored-by: mconnew <8648390+mconnew@users.noreply.github.com>
- Added detailed comments explaining why the linked CTS is not explicitly disposed - Clarified that HttpResponseMessageHelper has short lifetime and CTS will be garbage collected - Fixed CancellationToken default comparison to use CanBeCanceled check Co-authored-by: mconnew <8648390+mconnew@users.noreply.github.com>
- Added _linkedCts and _cachedCombinedToken fields to HttpResponseMessageHelper - Modified GetCombinedCancellationTokenAsync to cache the combined token on first call - This avoids creating multiple linked CancellationTokenSource instances - Improves resource management by creating only one CTS per helper instance Co-authored-by: mconnew <8648390+mconnew@users.noreply.github.com>
Fixes the issue where calling
Abort()on HTTP-based WCF channels doesn't cancel in-progress stream reads afterHttpClient.SendAsyncreturns. The abort signal now properly propagates to the response body reader.Problem
HTTP-based transports don't abort an in-progress request if the reply has already started. After
HttpClient.SendAsyncreturns anHttpResponseMessage, callingAbort()on the WCF channel doesn't propagate to the code receiving the response body, causing stream reads to hang until timeout.Solution
The fix follows the same pattern already used for the send phase:
Modified
HttpResponseMessageHelper:CancellationToken abortTokenparameter to constructor to receive the abort signalGetCombinedCancellationTokenAsync()helper method that combines the timeout token with the abort token usingCancellationTokenSource.CreateLinkedTokenSource()GetStreamAsync()ReadChunkedBufferedMessageAsync()ReadBufferedMessageAsync()DecodeBufferedMessageAsync()Modified
HttpClientChannelAsyncRequest.ReceiveReplyAsync():_httpSendCts.TokentoHttpResponseMessageHelperconstructorAbort()is called,_httpSendCtsis cancelled via the existingCleanup()methodTest Implementation
HttpStreamingAbortTests.4.1.0.cswith sync and async variantsCustomBindingwithTransferMode.StreamedResponse, reads partial data (1KB from 500KB stream), callsAbort(), then attempts continued readingCommunicationObjectAbortedException,IOException,CommunicationException, orOperationCanceledException. If broken, hangs untilReceiveTimeoutexpires.Tests use existing
CustomTextEncoderStreamedendpoint. Both synchronous and async patterns covered.Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.