Skip to content

Fix flaky ClientStreaming_ResponseCompletesWithoutResponseBodyWrite #20338

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

Merged
merged 2 commits into from
Apr 1, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 16 additions & 19 deletions src/Hosting/TestHost/src/HttpContextBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,25 @@ async Task RunRequestAsync()
// This could throw an error if there was a pending server read. Needs to
// happen before completing the response so the response returns the error.
var requestBodyInProgress = RequestBodyReadInProgress();
if (requestBodyInProgress)
{
// If request is still in progress then abort it.
CancelRequestBody();
}

// Matches Kestrel server: response is completed before request is drained
await CompleteResponseAsync();
await CompleteRequestAsync(requestBodyInProgress);

if (!requestBodyInProgress)
{
// Writer was already completed in send request callback.
await _requestPipe.Reader.CompleteAsync();

// Don't wait for request to drain. It could block indefinitely. In a real server
// we would wait for a timeout and then kill the socket.
// Potential future improvement: add logging that the request timed out
}

_application.DisposeContext(_testContext, exception: null);
}
catch (Exception ex)
Expand Down Expand Up @@ -165,24 +180,6 @@ internal void ClientInitiatedAbort()
CancelRequestBody();
}

private async Task CompleteRequestAsync(bool requestBodyInProgress)
{
if (requestBodyInProgress)
{
// If request is still in progress then abort it.
CancelRequestBody();
}
else
{
// Writer was already completed in send request callback.
await _requestPipe.Reader.CompleteAsync();
}

// Don't wait for request to drain. It could block indefinitely. In a real server
// we would wait for a timeout and then kill the socket.
// Potential future improvement: add logging that the request timed out
}

private bool RequestBodyReadInProgress()
{
try
Expand Down