Uh oh!
There was an error while loading. Please reload this page.
.NET: Fix off-thread RunStatus race where GetStatusAsync can return Running after ResumeAsync halts - #5412
Conversation
… after ResumeAsync halts
There was a problem hiding this comment.
Pull request overview
Fixes a race in the off-thread workflow run loop where RunStatus could transiently flip back to Running after a halt had already been observed, and adds a stress regression test to prevent reintroduction.
Changes:
- Update
StreamingRunEventStream.RunLoopAsyncto setRunStatus.Runningonly when there are unprocessed messages to run. - Add an off-thread stress regression test that repeatedly runs the Step9 sample to catch the previously intermittent status race.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| dotnet/src/Microsoft.Agents.AI.Workflows/Execution/StreamingRunEventStream.cs | Prevents stale input signals from transiently setting RunStatus back to Running when there is no work to process. |
| dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/SampleSmokeTest.cs | Adds a stress regression test targeting the Step9 multi-response resume scenario in off-thread execution. |
Uh oh!
There was an error while loading. Please reload this page.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Jacob Alber (lokitoth)
commented
Apr 23, 2026
Ah, guess I missed it, but for information purposes: I remember looking at this earlier in #2646; when I added tests for this, I noticed that Lockstep was semantically different in how it handled things, so there were some things to be done to get it to a happy state, but may be out of scope of this PR.
I'll bring over tests + any changes that are needed for them separately. |
Uh oh!
There was an error while loading. Please reload this page.
Motivation and Context
In
StreamingRunEventStream.RunLoopAsync, after every_inputWaiter.WaitForInputAsyncwake-up,_runStatuswas being flipped toRunningunconditionally. This can lead stale signal to flip status back to running after consumer already observed halt signal.Fixes#5411
Description
Only flip
RunStatustoRunningwhen there are messages to process.LockstepRunEventStreamis not affected — it runs supersteps synchronously on the consumer thread and has no comparable wake-up race.This addresses one of the intermittent workflow test failures in the pipeline.
Contribution Checklist