Skip to content

Fix wait_condition to wake registered wakers on state_mut - #1127

Closed
mfateev wants to merge 2 commits into
temporalio:rust-sdk-prereleasefrom
mfateev:fix/wait-condition-wakers
Closed

mfateev wants to merge 2 commits into
temporalio:rust-sdk-prereleasefrom
mfateev:fix/wait-condition-wakers

Conversation

@mfateev

@mfateev mfateev commented Feb 23, 2026

Copy link
Copy Markdown
Member

Summary

  • Fix deadlock when wait_condition futures are used inside waker-based combinators like FuturesUnordered. Previously, wait_condition returned Poll::Pending without registering a waker, so state_mut changes would never re-poll the condition.
  • Add condition_wakers: Rc<RefCell<Vec<Waker>>> to WorkflowContext — wakers are registered on Pending and drained/woken on every state_mut call.
  • Add test exercising wait_condition + FuturesUnordered with a timer-triggered state mutation.

Test plan

  • cargo check --tests passes with no new warnings
  • wait_condition_waker_in_futures_unordered test passes against mock history

🤖 Generated with Claude Code

@mfateev
mfateev requested a review from a team as a code owner February 23, 2026 05:11
@CLAassistant

CLAassistant commented Feb 23, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

wait_condition used poll_fn that ignored the waker context (_cx),
returning Poll::Pending without registering any waker. This works
at the top level of a workflow run method where the SDK re-polls
unconditionally on every activation. However, when wait_condition
is used inside a waker-based combinator like FuturesOrdered (e.g.
via a ToolCallHandler future), the combinator never re-polls the
inner future because no waker was triggered.

Fix: store the waker from cx when returning Pending, and drain/wake
all stored wakers after every state_mut call. This is deterministic
because wakers are purely in-process scheduling — no I/O, timers,
or randomness. All execution remains single-threaded on the LocalSet.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@mfateev
mfateev force-pushed the fix/wait-condition-wakers branch from 9b69124 to 7533b84 Compare February 23, 2026 05:32
Exercises the exact bug scenario: wait_condition inside FuturesUnordered,
which gives each sub-future its own waker and only re-polls when that
waker fires. Without the waker fix, this test hangs because
FuturesUnordered never re-polls the wait_condition future.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@chris-olszewski chris-olszewski left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This was addressed on master in https://github.com/temporalio/sdk-core/pull/1118/changes

I pulled out the test to #1128 as we should have coverage for this.

@mfateev

mfateev commented Feb 23, 2026

Copy link
Copy Markdown
Member Author

Great, I didn't realize that the release was from the master.

@mfateev mfateev closed this Feb 23, 2026
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