From 4a14ad3a835598a6623941ddd3a06591688cbc1f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 19 Mar 2026 21:41:15 +0000 Subject: [PATCH 1/2] Initial plan From be0b76a33cc070016044a216821d10ceb7f2753a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 19 Mar 2026 21:47:57 +0000 Subject: [PATCH 2/2] Fix thread-safety race in AllocLookup/FreeLookup using Interlocked operations Co-authored-by: brianrob <6210322+brianrob@users.noreply.github.com> --- src/TraceEvent/TraceLog.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/TraceEvent/TraceLog.cs b/src/TraceEvent/TraceLog.cs index 0897d5c36..b7957ae87 100644 --- a/src/TraceEvent/TraceLog.cs +++ b/src/TraceEvent/TraceLog.cs @@ -3662,21 +3662,20 @@ private void AddTemplatesForParser(TraceEventParser parser, TraceLogEventSource /// internal unsafe TraceEventDispatcher AllocLookup() { - if (freeLookup == null) + // Use Interlocked.Exchange to atomically take the cached dispatcher (setting the field to null). + // This prevents a race where two threads both read the non-null value before either sets it to null. + TraceEventDispatcher ret = Interlocked.Exchange(ref freeLookup, null); + if (ret == null) { - freeLookup = AddAllTemplatesToDispatcher(new TraceLogEventSource(events)); + ret = AddAllTemplatesToDispatcher(new TraceLogEventSource(events)); } - TraceEventDispatcher ret = freeLookup; - freeLookup = null; return ret; } internal unsafe void FreeLookup(TraceEventDispatcher lookup) { - if (freeLookup == null) - { - freeLookup = lookup; - } + // Use Interlocked.CompareExchange to atomically store the dispatcher back only if the slot is empty. + Interlocked.CompareExchange(ref freeLookup, lookup, null); } private void InitializeFromFile(string etlxFilePath)