Repository navigation
Prevent the circuit breaker from capturing the ambient ExecutionContext - #3284
Merged
martincostello merged 1 commit intoOct 24, 2026
Conversation
…xt (App-vNext#3275) ScheduledTaskExecutor starts its background processing loop with Task.Run in its constructor, which flows the ambient ExecutionContext. The loop lives as long as the pipeline, so every AsyncLocal value of the code that built the pipeline stays reachable for the pipeline's lifetime. Start the loop with the flow suppressed; the loop is infrastructure that belongs to no caller.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3284 +/- ##
=======================================
Coverage 98.02% 98.02%
=======================================
Files 321 321
Lines 7099 7103 +4
Branches 1089 1089
=======================================
+ Hits 6959 6963 +4
Misses 98 98
Partials 42 42
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. |
martincostello
approved these changes
Oct 24, 2026
This was referenced Oct 24, 2026
Contributor
|
Thanks for your contribution @Nacl-HCl - the changes from this pull request have been published as part of version 8.8.1 📦, which is now available from NuGet.org 🚀 |
This was referenced Oct 26, 2026
SonnyRR
pushed a commit
to SonnyRR/stacked-deck-templates
that referenced
this pull request
Oct 26, 2026
Updated [Polly](https://github.com/App-vNext/Polly) from 8.8.0 to 8.8.1. <details> <summary>Release notes</summary> _Sourced from [Polly's releases](https://github.com/App-vNext/Polly/releases)._ ## 8.8.1 ## Highlights * Prevent the circuit breaker from capturing the ambient ExecutionContext by @Nacl-HCl in App-vNext/Polly#3284 * Improve pipeline execution performance by @martincostello in App-vNext/Polly#3287 * Fix cleanup of discarded registry pipelines by @harshvarudkar in App-vNext/Polly#3288 ## What's Changed * Add Copilot code review skill by @martincostello in App-vNext/Polly#3247 * Fix benchmarks by @martincostello in App-vNext/Polly#3248 * Update PR template by @martincostello in App-vNext/Polly#3249 * Update README with OSMF details for Polly by @joelhulen in App-vNext/Polly#3263 * Fix lint warnings by @martincostello in App-vNext/Polly#3264 * Update FUNDING by @martincostello in App-vNext/Polly#3258 * Remove obsolete packages references by @martincostello in App-vNext/Polly#3267 * Validate packages in parallel by @martincostello in App-vNext/Polly#3283 * .NET 11 preparation by @martincostello in App-vNext/Polly#3285 ## New Contributors * @Nacl-HCl made their first contribution in App-vNext/Polly#3284 * @harshvarudkar made their first contribution in App-vNext/Polly#3288 **Full Changelog**: App-vNext/Polly@8.8.0...8.8.1 Commits viewable in [compare view](App-vNext/Polly@8.8.0...8.8.1). </details> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This was referenced Oct 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3275
The issue or feature being addressed
#3275
Details on the issue fix or feature implementation
ScheduledTaskExecutorstarts its background processing loop withTask.Run(StartProcessingAsync)in its constructor, which flows the ambientExecutionContextinto the loop. The loop waits on its semaphore for as longas the pipeline lives, so every
AsyncLocalvalue of the code that happenedto build the pipeline stays reachable for the pipeline's lifetime (e.g. the
first user's circuit in a Blazor Server app is never collected after it is
disposed).
The loop is infrastructure that belongs to no caller, and the scheduled tasks
are the breaker's own state-change callbacks, which a caller's ambient
AsyncLocalvalues should not reach either. The constructor now starts theloop with the flow suppressed:
Confirm the following
Verification
Constructor_DoesNotCaptureAmbientExecutionContext(in
ScheduledTaskExecutorTests): builds an executor while anAsyncLocal<object?>holds a value, then asserts the value is collectablewhile the executor (and its background task) is kept alive.
IsAliveisTrue— the leak reproduces)Polly.Core.Testsfull suite (net10.0): 782/782 passed, 0 failedPolly.Corebuilds clean for all target frameworks(net8.0;net6.0;netstandard2.0;net472;net462), 0 warnings, 0 errors
Note
This PR description was prepared with AI assistance (Muse). The fix and the
regression test were verified by running the reproduction and the test suite
locally as described above.