Skip to content

Fix reentrant Monitor wait#126071

Open
eduardo-vp wants to merge 4 commits intodotnet:mainfrom
eduardo-vp:fix-reentrant-monitor-wait-hang
Open

Fix reentrant Monitor wait#126071
eduardo-vp wants to merge 4 commits intodotnet:mainfrom
eduardo-vp:fix-reentrant-monitor-wait-hang

Conversation

@eduardo-vp
Copy link
Member

@eduardo-vp eduardo-vp commented Mar 25, 2026

Fixes #123173.

There's currently a problem with Monitor using a single thread-static Waiter (and AutoResetEvent) per thread. When using synchronization contexts that allow message pumping the following scenario can happen:

  • The main thread calls Monitor.Wait on lock A.
  • SynchronizationContext.Wait pumps a message and the main thread calls Monitor.Wait on lock B.
  • Since both operations were run on the same thread, both share the same waiter.
  • A background thread calls Monitor.Pulse on lock A but lock B steals the signal since they share the same waiter.

This change nulls out the thread-static Waiter while a wait is in progress, so any reentrant Monitor.Wait gets its own Waiter with a distinct AutoResetEvent. The Waiter is restored after the wait completes.

Copilot AI review requested due to automatic review settings March 25, 2026 03:31
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @agocke, @VSadov
See info in area-owners.md if you want to be subscribed.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes a Monitor.Wait reentrancy issue where nested waits on the same thread could share a single thread-static waiter/event, allowing one wait to consume (“steal”) another wait’s pulse, particularly when SynchronizationContext.Wait pumps messages.

Changes:

  • Adjust Condition.Waiter thread-static reuse to clear the cached waiter while a wait is in progress, ensuring overlapping waits use distinct AutoResetEvent instances.
  • Add a regression test that reproduces the message-pumping reentrant wait scenario via a custom SynchronizationContext.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/libraries/System.Private.CoreLib/src/System/Threading/Condition.cs Updates waiter caching logic so overlapping waits don’t share the same thread-static waiter/event.
src/libraries/System.Threading/tests/MonitorTests.cs Adds a regression test validating reentrant waits don’t steal each other’s pulse signals.
…ition.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 25, 2026 03:41
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

@eduardo-vp eduardo-vp requested review from VSadov and jkotas March 25, 2026 03:48
@jkotas jkotas requested a review from jkoritzinsky March 25, 2026 04:10
Copy link
Member

@VSadov VSadov left a comment

Choose a reason for hiding this comment

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

LGTM!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment