diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs index d43e49f92ca3d..ce477e02c9ef7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs @@ -7,6 +7,7 @@ using System.Globalization; using System.Numerics; using System.Runtime.InteropServices; +using System.Threading; #if ES_BUILD_STANDALONE using Microsoft.Win32; @@ -209,6 +210,7 @@ protected virtual void Dispose(bool disposing) // deadlocks in race conditions (dispose racing with an ETW command). // // We solve by Unregistering after releasing the EventListenerLock. + Debug.Assert(!Monitor.IsEntered(EventListener.EventListenersLock)); if (registrationHandle != 0) EventUnregister(registrationHandle); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs index 556e4e8df58fe..e47a6127022cf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs @@ -1449,6 +1449,10 @@ protected virtual void Dispose(bool disposing) return; } + // Do not invoke Dispose under the lock as this can lead to a deadlock. + // See https://github.com/dotnet/runtime/issues/48342 for details. + Debug.Assert(!Monitor.IsEntered(EventListener.EventListenersLock)); + if (disposing) { #if FEATURE_MANAGED_ETW @@ -4274,16 +4278,26 @@ internal static void DisposeOnShutdown() #endif { Debug.Assert(EventSource.IsSupported); - + List sourcesToDispose = new List(); lock (EventListenersLock) { Debug.Assert(s_EventSources != null); foreach (WeakReference esRef in s_EventSources) { if (esRef.TryGetTarget(out EventSource? es)) - es.Dispose(); + { + sourcesToDispose.Add(es); + } } } + + // Do not invoke Dispose under the lock as this can lead to a deadlock. + // See https://github.com/dotnet/runtime/issues/48342 for details. + Debug.Assert(!Monitor.IsEntered(EventListenersLock)); + foreach (EventSource es in sourcesToDispose) + { + es.Dispose(); + } } ///