From 90c1750027a0935a40f1db85d084261ea11b0d08 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 14 Jun 2021 20:15:17 -0400 Subject: [PATCH] Fix thread-safety of DiagnosticListener.AllListeners (#54142) --- .../src/System/Diagnostics/DiagnosticListener.cs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs index cd588e6..e06a927 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs @@ -39,12 +39,10 @@ namespace System.Diagnostics #if ENABLE_HTTP_HANDLER GC.KeepAlive(HttpHandlerDiagnosticListener.s_instance); #endif - - if (s_allListenerObservable == null) - { - s_allListenerObservable = new AllListenerObservable(); - } - return s_allListenerObservable; + return + s_allListenerObservable ?? + Interlocked.CompareExchange(ref s_allListenerObservable, new AllListenerObservable(), null) ?? + s_allListenerObservable; } } @@ -137,9 +135,7 @@ namespace System.Diagnostics lock (s_allListenersLock) { // Issue the callback for this new diagnostic listener. - var allListenerObservable = s_allListenerObservable; - if (allListenerObservable != null) - allListenerObservable.OnNewDiagnosticListener(this); + s_allListenerObservable?.OnNewDiagnosticListener(this); // And add it to the list of all past listeners. _next = s_allListeners; @@ -460,7 +456,7 @@ namespace System.Diagnostics private bool _disposed; // Has Dispose been called? private static DiagnosticListener? s_allListeners; // linked list of all instances of DiagnosticListeners. - private static AllListenerObservable? s_allListenerObservable; // to make callbacks to this object when listeners come into existence. + private static volatile AllListenerObservable? s_allListenerObservable; // to make callbacks to this object when listeners come into existence. private static readonly object s_allListenersLock = new object(); #if false private static readonly DiagnosticListener s_default = new DiagnosticListener("DiagnosticListener.DefaultListener"); -- 2.7.4