Skip to content

Conversation

@DavidPoulsenHGS
Copy link

Description

Fixes deadlock prone code in HttpConnection.cs. Changed synchronous methods in HttpConnection.cs to use Task.Run/Task.Wait to avoid deadlocks in accordance with: https://learn.microsoft.com/en-us/archive/blogs/jpsanders/asp-net-do-not-use-task-result-in-main-context

Issues Resolved

#689

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

{
receive = DiagnosticSource.Diagnose(DiagnosticSources.HttpConnection.ReceiveBody, requestData, statusCode);
responseStream = responseMessage.Content.ReadAsStreamAsync().GetAwaiter().GetResult();
var task = Task.Run(() => responseMessage.Content.ReadAsStreamAsync());
Copy link
Contributor

Choose a reason for hiding this comment

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

have you considered just changing it to responseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false)?

threadPoolStats = ThreadPoolStats.GetStats();

responseMessage = client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead).GetAwaiter().GetResult();
var task = Task.Run(() => client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead));
Copy link
Contributor

Choose a reason for hiding this comment

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

have you looked at using client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false)?

Copy link

Choose a reason for hiding this comment

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

@joefeser .ConfigureAwait(false) is not needed inside a Task.Run since there is no synchronization context to capture.

@Salgat
Copy link

Salgat commented May 13, 2025

Using .GetAwaiter().GetResult() in a library is considered a massive problem since it does open the door to deadlocks. As a last resort, Task.Run(...).Wait() is definitely better than the current .GetAwaiter().GetResult(), but the more appropriate option is to remove the synchronous interface altogether if it's just wrapping an async call in a synchronous wait. At that point, the user of the library can do that themselves using their own judgment on whether it's necessary and with full knowledge of what is happening.

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.

3 participants