Add missing ConfigureAwait(false) to prevent deadlocks#2367
Add missing ConfigureAwait(false) to prevent deadlocks#2367alexeyzimarev merged 2 commits intodevfrom
Conversation
Fixes #2083 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Review Summary by QodoAdd missing ConfigureAwait(false) to prevent deadlocks
WalkthroughsDescription• Adds missing .ConfigureAwait(false) to prevent sync-over-async deadlocks • Fixes deadlock in ExecuteGet when used with ThreadPool • Ensures proper context handling in .NET Framework and WinForms/WPF • Covers four critical async methods across RestSharp codebase Diagramflowchart LR
A["Sync Methods<br/>ExecuteGet"] -->|calls| B["AsyncHelpers.RunSync"]
B -->|awaits| C["Async Operations<br/>without ConfigureAwait"]
C -->|captures| D["SynchronizationContext"]
D -->|causes| E["Deadlock"]
F["Fix: Add<br/>ConfigureAwait(false)"] -->|prevents| D
File Changes1. src/RestSharp/Extensions/HttpResponseExtensions.cs
|
Code Review by Qodo
1. RestResponse.cs header mismatch
|
|
|
||
| var bytes = stream == null ? null : await stream.ReadAsBytes(cancellationToken).ConfigureAwait(false); | ||
| var content = bytes == null ? null : await httpResponse.GetResponseString(bytes, options.Encoding); | ||
| var content = bytes == null ? null : await httpResponse.GetResponseString(bytes, options.Encoding).ConfigureAwait(false); |
There was a problem hiding this comment.
1. Restresponse.cs header mismatch 📘 Rule violation ✓ Correctness
src/RestSharp/Response/RestResponse.cs does not contain the exact required Apache-2.0 license header text even though the file is modified in this PR. This fails the repository licensing compliance requirement for changed /src C# files.
Agent Prompt
## Issue description
`src/RestSharp/Response/RestResponse.cs` does not match the repository’s exact required Apache-2.0 license header text.
## Issue Context
Compliance requires every modified `/src` C# file to include the exact header as defined in `.github/copilot-instructions.md`.
## Fix Focus Areas
- src/RestSharp/Response/RestResponse.cs[1-14]
- .github/copilot-instructions.md[65-81]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| Ensure.NotNull(request, nameof(request)); | ||
|
|
||
| var response = await client.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); | ||
| return await client.Serializers.Deserialize<T>(request, response, client.Options, cancellationToken); | ||
| return await client.Serializers.Deserialize<T>(request, response, client.Options, cancellationToken).ConfigureAwait(false); | ||
| } |
There was a problem hiding this comment.
2. Deadlock fix lacks tests 📘 Rule violation ⛯ Reliability
This PR changes async flow to prevent sync-over-async deadlocks, but it does not add/update tests to cover the reported hang scenario. Without a regression test, the deadlock could reappear unnoticed.
Agent Prompt
## Issue description
The PR fixes a deadlock risk (sync-over-async) by adding `.ConfigureAwait(false)`, but there is no regression test to ensure the original hang scenario stays fixed.
## Issue Context
The reported issue involves sync methods (like `ExecuteGet`/`AsyncHelpers.RunSync`) hanging when invoked from ThreadPool work items due to `SynchronizationContext` capture.
## Fix Focus Areas
- src/RestSharp/RestClient.Extensions.cs[41-49]
- test/RestSharp.Tests/Fixtures/MockHttpClient.cs[1-17]
- test/RestSharp.Tests/[new test file covering ThreadPool ExecuteGet scenario]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Test Results 42 files 42 suites 17m 37s ⏱️ Results for commit b4dc236. |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|



Summary
.ConfigureAwait(false)to allawaitcalls in the RestSharp source that were missing it, preventing sync-over-async deadlocks on .NET Framework and environments with aSynchronizationContext(WinForms, WPF, ASP.NET classic)HttpResponseExtensions.GetResponseString,RestResponse.FromHttpResponse,RestClientExtensions.ExecuteAsync<T>, andRestClientExtensions.StreamJsonAsync<T>Fixes #2083
Context
Reported by @deAtog in #2083 (comment) — when sync methods like
ExecuteGetare used (which internally callAsyncHelpers.RunSync), any nestedawaitwithout.ConfigureAwait(false)can capture the synchronization context and deadlock.Test plan
awaitcalls without.ConfigureAwait(false)insrc/RestSharp/🤖 Generated with Claude Code