From 96f42a0df02808b42e4723c5e0ea50e5cb063a5a Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Tue, 5 May 2020 17:00:58 +0200 Subject: [PATCH 1/9] avoid double flush hit files for collectors --- .../InProcDataCollection/CoverletInProcDataCollector.cs | 1 + src/coverlet.core/Instrumentation/Instrumenter.cs | 5 +++++ src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs | 6 ++++++ 3 files changed, 12 insertions(+) diff --git a/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs b/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs index c48c2dd86..4ce04bdfe 100644 --- a/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs +++ b/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs @@ -56,6 +56,7 @@ public void TestSessionEnd(TestSessionEndArgs testSessionEndArgs) _eqtTrace.Verbose($"Calling ModuleTrackerTemplate.UnloadModule for '{injectedInstrumentationClass.Assembly.FullName}'"); var unloadModule = injectedInstrumentationClass.GetMethod(nameof(ModuleTrackerTemplate.UnloadModule), new[] { typeof(object), typeof(EventArgs) }); unloadModule.Invoke(null, new[] { null, EventArgs.Empty }); + injectedInstrumentationClass.GetField("FlushHitFile", BindingFlags.Static | BindingFlags.Public).SetValue(null, false); _eqtTrace.Verbose($"Called ModuleTrackerTemplate.UnloadModule for '{injectedInstrumentationClass.Assembly.FullName}'"); } catch (Exception ex) diff --git a/src/coverlet.core/Instrumentation/Instrumenter.cs b/src/coverlet.core/Instrumentation/Instrumenter.cs index 376bfb43f..86e32bca2 100644 --- a/src/coverlet.core/Instrumentation/Instrumenter.cs +++ b/src/coverlet.core/Instrumentation/Instrumenter.cs @@ -34,6 +34,7 @@ internal class Instrumenter private FieldDefinition _customTrackerHitsArray; private FieldDefinition _customTrackerHitsFilePath; private FieldDefinition _customTrackerSingleHit; + private FieldDefinition _customTrackerFlushHitFile; private ILProcessor _customTrackerClassConstructorIl; private TypeDefinition _customTrackerTypeDef; private MethodReference _customTrackerRegisterUnloadEventsMethod; @@ -243,6 +244,8 @@ private void InstrumentModule() _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Stsfld, _customTrackerHitsFilePath)); _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(_singleHit ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0)); _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Stsfld, _customTrackerSingleHit)); + _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Ldc_I4_1)); + _customTrackerClassConstructorIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Stsfld, _customTrackerFlushHitFile)); if (containsAppContext) { @@ -294,6 +297,8 @@ private void AddCustomModuleTrackerToModule(ModuleDefinition module) _customTrackerHitsFilePath = fieldClone; else if (fieldClone.Name == nameof(ModuleTrackerTemplate.SingleHit)) _customTrackerSingleHit = fieldClone; + else if (fieldClone.Name == nameof(ModuleTrackerTemplate.FlushHitFile)) + _customTrackerFlushHitFile = fieldClone; } foreach (MethodDefinition methodDef in moduleTrackerTemplate.Methods) diff --git a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs index b3ae4e302..2806674b9 100644 --- a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs +++ b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs @@ -21,6 +21,7 @@ internal static class ModuleTrackerTemplate public static string HitsFilePath; public static int[] HitsArray; public static bool SingleHit; + public static bool FlushHitFile; private static readonly bool _enableLog = int.TryParse(Environment.GetEnvironmentVariable("COVERLET_ENABLETRACKERLOG"), out int result) ? result == 1 : false; static ModuleTrackerTemplate() @@ -75,6 +76,11 @@ public static void RecordSingleHit(int hitLocationIndex) public static void UnloadModule(object sender, EventArgs e) { + if (!FlushHitFile) + { + return; + } + try { WriteLog($"Unload called for '{Assembly.GetExecutingAssembly().Location}'"); From 1ce2fb4d2dc84d5eca641c08e6d347fbe22eaf99 Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Tue, 5 May 2020 17:19:33 +0200 Subject: [PATCH 2/9] fix test --- test/coverlet.core.tests/Coverage/InstrumenterHelper.cs | 7 ++++++- .../Instrumentation/ModuleTrackerTemplateTests.cs | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/test/coverlet.core.tests/Coverage/InstrumenterHelper.cs b/test/coverlet.core.tests/Coverage/InstrumenterHelper.cs index e8d17ee82..fb7a63c28 100644 --- a/test/coverlet.core.tests/Coverage/InstrumenterHelper.cs +++ b/test/coverlet.core.tests/Coverage/InstrumenterHelper.cs @@ -26,7 +26,7 @@ static class TestInstrumentationHelper /// caller sample: TestInstrumentationHelper.GenerateHtmlReport(result, sourceFileFilter: @"+**\Samples\Instrumentation.cs"); /// TestInstrumentationHelper.GenerateHtmlReport(result); /// - public static void GenerateHtmlReport(CoverageResult coverageResult, IReporter reporter = null, string sourceFileFilter = "", [CallerMemberName]string directory = "") + public static void GenerateHtmlReport(CoverageResult coverageResult, IReporter reporter = null, string sourceFileFilter = "", [CallerMemberName] string directory = "") { JsonReporter defaultReporter = new JsonReporter(); reporter ??= new CoberturaReporter(); @@ -290,5 +290,10 @@ public static void RunInProcess(this FunctionExecutor executor, Func> func) + { + Assert.Equal(0, func().Result); + } } } diff --git a/test/coverlet.core.tests/Instrumentation/ModuleTrackerTemplateTests.cs b/test/coverlet.core.tests/Instrumentation/ModuleTrackerTemplateTests.cs index 4bbaccbe8..8195c7221 100644 --- a/test/coverlet.core.tests/Instrumentation/ModuleTrackerTemplateTests.cs +++ b/test/coverlet.core.tests/Instrumentation/ModuleTrackerTemplateTests.cs @@ -14,6 +14,7 @@ class TrackerContext : IDisposable public TrackerContext() { ModuleTrackerTemplate.HitsFilePath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + ModuleTrackerTemplate.FlushHitFile = true; } public void Dispose() From 9c542cfafaf1e93bb5ec4d070bf41b3416779a9a Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Tue, 5 May 2020 17:25:24 +0200 Subject: [PATCH 3/9] nit: cleanup --- .../Instrumentation/ModuleTrackerTemplateTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/coverlet.core.tests/Instrumentation/ModuleTrackerTemplateTests.cs b/test/coverlet.core.tests/Instrumentation/ModuleTrackerTemplateTests.cs index 8195c7221..bda2ff8ea 100644 --- a/test/coverlet.core.tests/Instrumentation/ModuleTrackerTemplateTests.cs +++ b/test/coverlet.core.tests/Instrumentation/ModuleTrackerTemplateTests.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using Coverlet.Core.Instrumentation; -using Coverlet.Tests.Xunit.Extensions; using Xunit; namespace Coverlet.Core.Tests.Instrumentation From 6316f5fc24cd9adc0427664cc07484bf17d23298 Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Fri, 8 May 2020 22:44:43 +0200 Subject: [PATCH 4/9] fix log --- .../XUnitTestProject1.csproj | 2 +- .../Instrumentation/ModuleTrackerTemplate.cs | 37 ++++++++++--------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/Documentation/Examples/VSTest/HelloWorld/XUnitTestProject1/XUnitTestProject1.csproj b/Documentation/Examples/VSTest/HelloWorld/XUnitTestProject1/XUnitTestProject1.csproj index 7657ba024..3000c34e8 100644 --- a/Documentation/Examples/VSTest/HelloWorld/XUnitTestProject1/XUnitTestProject1.csproj +++ b/Documentation/Examples/VSTest/HelloWorld/XUnitTestProject1/XUnitTestProject1.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs index 2806674b9..b95d71392 100644 --- a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs +++ b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs @@ -81,20 +81,21 @@ public static void UnloadModule(object sender, EventArgs e) return; } - try - { - WriteLog($"Unload called for '{Assembly.GetExecutingAssembly().Location}'"); - // Claim the current hits array and reset it to prevent double-counting scenarios. - int[] hitsArray = Interlocked.Exchange(ref HitsArray, new int[HitsArray.Length]); + // Claim the current hits array and reset it to prevent double-counting scenarios. + int[] hitsArray = Interlocked.Exchange(ref HitsArray, new int[HitsArray.Length]); - // The same module can be unloaded multiple times in the same process via different app domains. - // Use a global mutex to ensure no concurrent access. - using (var mutex = new Mutex(true, Path.GetFileNameWithoutExtension(HitsFilePath) + "_Mutex", out bool createdNew)) + // The same module can be unloaded multiple times in the same process via different app domains. + // Use a global mutex to ensure no concurrent access. + using (var mutex = new Mutex(true, Path.GetFileNameWithoutExtension(HitsFilePath) + "_Mutex", out bool createdNew)) + { + try { - WriteLog($"Flushing hit file '{HitsFilePath}'"); if (!createdNew) mutex.WaitOne(); + WriteLog($"Unload called for '{Assembly.GetExecutingAssembly().Location}'"); + WriteLog($"Flushing hit file '{HitsFilePath}'"); + bool failedToCreateNewHitsFile = false; try { @@ -110,7 +111,7 @@ public static void UnloadModule(object sender, EventArgs e) } catch (Exception ex) { - WriteLog($"Failed to create new hits file '{HitsFilePath}'\n{ex}"); + WriteLog($"Failed to create new hits file '{HitsFilePath}' -> '{ex.Message}'"); failedToCreateNewHitsFile = true; } @@ -145,16 +146,16 @@ public static void UnloadModule(object sender, EventArgs e) WriteHits(); - // On purpose this is not under a try-finally: it is better to have an exception if there was any error writing the hits file - // this case is relevant when instrumenting corelib since multiple processes can be running against the same instrumented dll. - mutex.ReleaseMutex(); WriteLog($"Hit file '{HitsFilePath}' flushed, size {new FileInfo(HitsFilePath).Length}"); } - } - catch (Exception ex) - { - WriteLog(ex.ToString()); - throw; + catch (Exception ex) + { + WriteLog(ex.ToString()); + throw; + } + // On purpose this is not under a try-finally: it is better to have an exception if there was any error writing the hits file + // this case is relevant when instrumenting corelib since multiple processes can be running against the same instrumented dll. + mutex.ReleaseMutex(); } } From 81e92c1c356b4cd21057a425ad8648917985c44c Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Sat, 9 May 2020 18:38:22 +0200 Subject: [PATCH 5/9] imrpove logging --- .../CoverletInProcDataCollector.cs | 2 +- .../Instrumentation/ModuleTrackerTemplate.cs | 119 +++++++++--------- 2 files changed, 64 insertions(+), 57 deletions(-) diff --git a/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs b/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs index 4ce04bdfe..8c4dd05ef 100644 --- a/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs +++ b/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs @@ -55,7 +55,7 @@ public void TestSessionEnd(TestSessionEndArgs testSessionEndArgs) { _eqtTrace.Verbose($"Calling ModuleTrackerTemplate.UnloadModule for '{injectedInstrumentationClass.Assembly.FullName}'"); var unloadModule = injectedInstrumentationClass.GetMethod(nameof(ModuleTrackerTemplate.UnloadModule), new[] { typeof(object), typeof(EventArgs) }); - unloadModule.Invoke(null, new[] { null, EventArgs.Empty }); + unloadModule.Invoke(null, new[] { (object)this, EventArgs.Empty }); injectedInstrumentationClass.GetField("FlushHitFile", BindingFlags.Static | BindingFlags.Public).SetValue(null, false); _eqtTrace.Verbose($"Called ModuleTrackerTemplate.UnloadModule for '{injectedInstrumentationClass.Assembly.FullName}'"); } diff --git a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs index b95d71392..cee1efc74 100644 --- a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs +++ b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs @@ -76,11 +76,6 @@ public static void RecordSingleHit(int hitLocationIndex) public static void UnloadModule(object sender, EventArgs e) { - if (!FlushHitFile) - { - return; - } - // Claim the current hits array and reset it to prevent double-counting scenarios. int[] hitsArray = Interlocked.Exchange(ref HitsArray, new int[HitsArray.Length]); @@ -88,78 +83,90 @@ public static void UnloadModule(object sender, EventArgs e) // Use a global mutex to ensure no concurrent access. using (var mutex = new Mutex(true, Path.GetFileNameWithoutExtension(HitsFilePath) + "_Mutex", out bool createdNew)) { - try + if (!createdNew) { - if (!createdNew) - mutex.WaitOne(); - - WriteLog($"Unload called for '{Assembly.GetExecutingAssembly().Location}'"); - WriteLog($"Flushing hit file '{HitsFilePath}'"); + mutex.WaitOne(); + } - bool failedToCreateNewHitsFile = false; + if (FlushHitFile) + { try { - using (var fs = new FileStream(HitsFilePath, FileMode.CreateNew)) - using (var bw = new BinaryWriter(fs)) + + WriteLog($"Unload called for '{Assembly.GetExecutingAssembly().Location}' by '{sender}'"); + WriteLog($"Flushing hit file '{HitsFilePath}'"); + + bool failedToCreateNewHitsFile = false; + try { - bw.Write(hitsArray.Length); - foreach (int hitCount in hitsArray) + using (var fs = new FileStream(HitsFilePath, FileMode.CreateNew)) + using (var bw = new BinaryWriter(fs)) { - bw.Write(hitCount); + bw.Write(hitsArray.Length); + foreach (int hitCount in hitsArray) + { + bw.Write(hitCount); + } } } - } - catch (Exception ex) - { - WriteLog($"Failed to create new hits file '{HitsFilePath}' -> '{ex.Message}'"); - failedToCreateNewHitsFile = true; - } - - if (failedToCreateNewHitsFile) - { - // Update the number of hits by adding value on disk with the ones on memory. - // This path should be triggered only in the case of multiple AppDomain unloads. - using (var fs = new FileStream(HitsFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) - using (var br = new BinaryReader(fs)) - using (var bw = new BinaryWriter(fs)) + catch (Exception ex) { - int hitsLength = br.ReadInt32(); - WriteLog($"Current hits found '{hitsLength}'"); - - if (hitsLength != hitsArray.Length) - { - throw new InvalidOperationException( - $"{HitsFilePath} has {hitsLength} entries but on memory {nameof(HitsArray)} has {hitsArray.Length}"); - } + WriteLog($"Failed to create new hits file '{HitsFilePath}' -> '{ex.Message}'"); + failedToCreateNewHitsFile = true; + } - for (int i = 0; i < hitsLength; ++i) + if (failedToCreateNewHitsFile) + { + // Update the number of hits by adding value on disk with the ones on memory. + // This path should be triggered only in the case of multiple AppDomain unloads. + using (var fs = new FileStream(HitsFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) + using (var br = new BinaryReader(fs)) + using (var bw = new BinaryWriter(fs)) { - int oldHitCount = br.ReadInt32(); - bw.Seek(-sizeof(int), SeekOrigin.Current); - if (SingleHit) - bw.Write(hitsArray[i] + oldHitCount > 0 ? 1 : 0); - else - bw.Write(hitsArray[i] + oldHitCount); + int hitsLength = br.ReadInt32(); + WriteLog($"Current hits found '{hitsLength}'"); + + if (hitsLength != hitsArray.Length) + { + throw new InvalidOperationException( + $"{HitsFilePath} has {hitsLength} entries but on memory {nameof(HitsArray)} has {hitsArray.Length}"); + } + + for (int i = 0; i < hitsLength; ++i) + { + int oldHitCount = br.ReadInt32(); + bw.Seek(-sizeof(int), SeekOrigin.Current); + if (SingleHit) + { + bw.Write(hitsArray[i] + oldHitCount > 0 ? 1 : 0); + } + else + { + bw.Write(hitsArray[i] + oldHitCount); + } + } } } - } - WriteHits(); + WriteHits(sender); - WriteLog($"Hit file '{HitsFilePath}' flushed, size {new FileInfo(HitsFilePath).Length}"); - } - catch (Exception ex) - { - WriteLog(ex.ToString()); - throw; + WriteLog($"Hit file '{HitsFilePath}' flushed, size {new FileInfo(HitsFilePath).Length}"); + WriteLog("--------------------------------"); + } + catch (Exception ex) + { + WriteLog(ex.ToString()); + throw; + } } + // On purpose this is not under a try-finally: it is better to have an exception if there was any error writing the hits file // this case is relevant when instrumenting corelib since multiple processes can be running against the same instrumented dll. mutex.ReleaseMutex(); } } - private static void WriteHits() + private static void WriteHits(object sender) { if (_enableLog) { @@ -179,7 +186,7 @@ private static void WriteHits() } } - File.AppendAllText(logFile, "Hits flushed"); + File.AppendAllText(logFile, $"Hits flushed file path {HitsFilePath} location '{Assembly.GetExecutingAssembly().Location}' by '{sender}'"); } } From da551b5b3c3aa6d248489cd51b6937e978c50ea3 Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Sat, 9 May 2020 19:14:33 +0200 Subject: [PATCH 6/9] move all code under mutex --- src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs index cee1efc74..27adcc198 100644 --- a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs +++ b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs @@ -76,9 +76,6 @@ public static void RecordSingleHit(int hitLocationIndex) public static void UnloadModule(object sender, EventArgs e) { - // Claim the current hits array and reset it to prevent double-counting scenarios. - int[] hitsArray = Interlocked.Exchange(ref HitsArray, new int[HitsArray.Length]); - // The same module can be unloaded multiple times in the same process via different app domains. // Use a global mutex to ensure no concurrent access. using (var mutex = new Mutex(true, Path.GetFileNameWithoutExtension(HitsFilePath) + "_Mutex", out bool createdNew)) @@ -88,11 +85,13 @@ public static void UnloadModule(object sender, EventArgs e) mutex.WaitOne(); } + // Claim the current hits array and reset it to prevent double-counting scenarios. + int[] hitsArray = Interlocked.Exchange(ref HitsArray, new int[HitsArray.Length]); + if (FlushHitFile) { try { - WriteLog($"Unload called for '{Assembly.GetExecutingAssembly().Location}' by '{sender}'"); WriteLog($"Flushing hit file '{HitsFilePath}'"); From 43c88d854ee3846a4951420bcbc469543fc41867 Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Sun, 10 May 2020 16:59:56 +0200 Subject: [PATCH 7/9] improve log --- src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs index 27adcc198..d8dda7d6f 100644 --- a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs +++ b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs @@ -92,7 +92,7 @@ public static void UnloadModule(object sender, EventArgs e) { try { - WriteLog($"Unload called for '{Assembly.GetExecutingAssembly().Location}' by '{sender}'"); + WriteLog($"Unload called for '{Assembly.GetExecutingAssembly().Location}' by '{sender ?? "null"}'"); WriteLog($"Flushing hit file '{HitsFilePath}'"); bool failedToCreateNewHitsFile = false; @@ -185,7 +185,7 @@ private static void WriteHits(object sender) } } - File.AppendAllText(logFile, $"Hits flushed file path {HitsFilePath} location '{Assembly.GetExecutingAssembly().Location}' by '{sender}'"); + File.AppendAllText(logFile, $"Hits flushed file path {HitsFilePath} location '{Assembly.GetExecutingAssembly().Location}' by '{sender ?? "null"}'"); } } From a46b3e5ae8171c7d45e680a00b8162063bd3ed10 Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Sun, 10 May 2020 17:02:06 +0200 Subject: [PATCH 8/9] nit: style --- src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs index d8dda7d6f..eab384644 100644 --- a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs +++ b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs @@ -127,8 +127,7 @@ public static void UnloadModule(object sender, EventArgs e) if (hitsLength != hitsArray.Length) { - throw new InvalidOperationException( - $"{HitsFilePath} has {hitsLength} entries but on memory {nameof(HitsArray)} has {hitsArray.Length}"); + throw new InvalidOperationException($"{HitsFilePath} has {hitsLength} entries but on memory {nameof(HitsArray)} has {hitsArray.Length}"); } for (int i = 0; i < hitsLength; ++i) From 44aa30aa0ee5564e88b141285cec40afb46d4056 Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Sun, 10 May 2020 17:07:45 +0200 Subject: [PATCH 9/9] move code under mutex --- src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs index eab384644..251dcac24 100644 --- a/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs +++ b/src/coverlet.core/Instrumentation/ModuleTrackerTemplate.cs @@ -85,13 +85,13 @@ public static void UnloadModule(object sender, EventArgs e) mutex.WaitOne(); } - // Claim the current hits array and reset it to prevent double-counting scenarios. - int[] hitsArray = Interlocked.Exchange(ref HitsArray, new int[HitsArray.Length]); - if (FlushHitFile) { try { + // Claim the current hits array and reset it to prevent double-counting scenarios. + int[] hitsArray = Interlocked.Exchange(ref HitsArray, new int[HitsArray.Length]); + WriteLog($"Unload called for '{Assembly.GetExecutingAssembly().Location}' by '{sender ?? "null"}'"); WriteLog($"Flushing hit file '{HitsFilePath}'");