Skip to content

Fix deadlock between EventListenersLock and ArrayPoolEventSource static ctor - #131501

Merged
mdh1418 merged 2 commits into
dotnet:mainfrom
mdh1418:mdh1418/fix-arraypooleventsource-deadlock
Jul 29, 2026
Merged

Fix deadlock between EventListenersLock and ArrayPoolEventSource static ctor#131501
mdh1418 merged 2 commits into
dotnet:mainfrom
mdh1418:mdh1418/fix-arraypooleventsource-deadlock

Conversation

@mdh1418

@mdh1418 mdh1418 commented Jul 28, 2026

Copy link
Copy Markdown
Member

Fixes #119014

Starting  dotnet-counters  during .NET app initialization can deadlock two threads with a lock-order cycle:

• Thread A holds  EventListenersLock  (inside  EventSource.DoCommand  for  MetricsEventSource ) and triggers the first-ever use of  ArrayPool  via string interpolation in  ParseSpecs . This causes  SharedArrayPool.Rent()  to access  ArrayPoolEventSource.Log , which needs  ArrayPoolEventSource 's type-init lock — held by Thread B.
• Thread B is running  ArrayPoolEventSource 's static constructor (holds the type-init lock) and is blocked waiting for  EventListenersLock .

The fix pre-initializes  ArrayPoolEventSource  in  InitializeDefaultEventSources() , following the identical pattern already used to fix the analogous  FrameworkEventSource  deadlock in  #126591  (PR  #126737 ). After pre-initialization,  ArrayPoolEventSource.Log  is never uninitialized when  Rent()  accesses it, so no type-init lock is ever needed — the cycle cannot form.

…c ctor

MetricsEventSource.ParseSpecs uses string interpolation, which calls
SharedArrayPool<char>.Rent(). That method accesses ArrayPoolEventSource.Log,
triggering ArrayPoolEventSource's static constructor on first use. Since
DoCommand runs while holding EventListenersLock, if a concurrent thread is
already running ArrayPoolEventSource's static constructor (which itself
acquires EventListenersLock), a deadlock results.

Fix: eagerly pre-initialize ArrayPoolEventSource in InitializeDefaultEventSources,
following the identical pattern used to fix the FrameworkEventSource deadlock
in dotnet#126591 (PR dotnet#126737).

Fixes dotnet#119014

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @dotnet/area-system-diagnostics-tracing
See info in area-owners.md if you want to be subscribed.

Copilot AI left a comment

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.

Pull request overview

This PR proactively initializes System.Buffers.ArrayPoolEventSource during EventSource.InitializeDefaultEventSources() to avoid a lock-order deadlock that can occur when ArrayPoolEventSource type-initialization is triggered while EventListener.EventListenersLock is held (notably during EventSource command handling paths).

Changes:

  • Pre-initialize System.Buffers.ArrayPoolEventSource.Log alongside other early-initialized default EventSources.
  • Add an explanatory comment documenting the deadlock scenario and why early initialization prevents it.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 29, 2026 01:19

Copilot AI left a comment

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.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

@mdh1418
mdh1418 merged commit 9fb40cc into dotnet:main Jul 29, 2026
141 checks passed
@mdh1418
mdh1418 deleted the mdh1418/fix-arraypooleventsource-deadlock branch July 29, 2026 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deadlock between EventListenerLock and ArrayPoolEventSource static ctor

4 participants