Skip to content

fix: scheduler can no longer yield if protobuf mutex is held#473

Merged
chris-olszewski merged 9 commits into
mainfrom
olszewski/fix_protobuf_blocking_cmd_creation
Jul 5, 2026
Merged

fix: scheduler can no longer yield if protobuf mutex is held#473
chris-olszewski merged 9 commits into
mainfrom
olszewski/fix_protobuf_blocking_cmd_creation

Conversation

@chris-olszewski

@chris-olszewski chris-olszewski commented Jul 2, 2026

Copy link
Copy Markdown
Member

What was changed

Scheduler#run_until_all_yielded will no longer return if the Google protobuf mutex is held.

This is done by inspecting block calls to see if the blocker is a mutex with google/protobuf in the path. This is more fragile than desired (as shown by how we test this behavior), but is already how we allowlist this mutex usage in IllegalWorkflowCallValidator so we are at least consistent in what we allow.

These block calls that come from the protobuf mutex will be tracked additionally and any Fiber that is blocked because of this will prevent us from considering that all ready fibers have been resumed.

Why?

We special case allow mutex usage from protobuf in the workflow as it is "safe" usage (as in it cannot cause non-determinism, it guards a cache to avoid unnecessary allocations). This is still not fully safe as if the workflow future is blocked waiting for this call, Scheduler#run_until_all_yielded can return even if there is additional work to do for this activation once the protobuf mutex is acquired. This resulted in "partial" workflow activations that could not be replayed consistently.

The issue is that the mutex used by protobuf is process wide so a worker that executes both activities and workflows will have the workflow threads fight with the activity threads for the mutex. This along with general CPU pressure could increase the chance of this mutex having contention.

We cannot warm this cache as it is backed by WeakMap.

Checklist

  1. Closes [Bug] Sync primitives can lead to un-replayable workflow history. #464

  2. How was this tested:

Added some fairly forced regression tests. Added some unit tests for our scheduler directly since those are the most worrisome changes.

  1. Any docs updates needed?
    N/A

@chris-olszewski
chris-olszewski force-pushed the olszewski/fix_protobuf_blocking_cmd_creation branch from 3ba74cd to 767fa5d Compare July 2, 2026 15:09
@chris-olszewski
chris-olszewski marked this pull request as ready for review July 2, 2026 16:51
@chris-olszewski
chris-olszewski requested a review from a team as a code owner July 2, 2026 16:51
Comment thread temporalio/test/google/protobuf/scheduler_mutex_wait.rb
end
assert_thread_blocking_fiber_count(scheduler, 1)
assert_empty after_mutex
assert_empty drain_result

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Are there any conditions where this could return something else? Just making sure I understand.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Since we're holding onto our fake protobuf mutex, we want to verify that this never emits any "commands". If this was ever non-empty that would mean we emitted commands even under the scenario we're trying to prevent.

@chris-olszewski
chris-olszewski force-pushed the olszewski/fix_protobuf_blocking_cmd_creation branch from 253e67b to 2ce894a Compare July 5, 2026 19:21
@chris-olszewski
chris-olszewski merged commit af8d929 into main Jul 5, 2026
14 of 15 checks passed
@chris-olszewski
chris-olszewski deleted the olszewski/fix_protobuf_blocking_cmd_creation branch July 5, 2026 23:03
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.

[Bug] Sync primitives can lead to un-replayable workflow history.

2 participants