Skip to content

Commit 8521556

Browse files
John Salemgithub-actions
John Salem
authored and
github-actions
committed
Fix #53564 * default internal state to DateTime.MaxValue * re-check IsEnabled after not holding lock * add test for setting interval to 0
1 parent a33b642 commit 8521556

File tree

3 files changed

+126
-5
lines changed

3 files changed

+126
-5
lines changed

src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/CounterGroup.cs

+10-5
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,15 @@ internal static CounterGroup GetCounterGroup(EventSource eventSource)
116116

117117
private DateTime _timeStampSinceCollectionStarted;
118118
private int _pollingIntervalInMilliseconds;
119-
private DateTime _nextPollingTimeStamp;
119+
private DateTime _nextPollingTimeStamp = DateTime.MaxValue;
120120

121121
private void EnableTimer(float pollingIntervalInSeconds)
122122
{
123123
Debug.Assert(Monitor.IsEntered(s_counterGroupLock));
124124
if (pollingIntervalInSeconds <= 0)
125125
{
126126
_pollingIntervalInMilliseconds = 0;
127+
_nextPollingTimeStamp = DateTime.MaxValue;
127128
}
128129
else if (_pollingIntervalInMilliseconds == 0 || pollingIntervalInSeconds * 1000 < _pollingIntervalInMilliseconds)
129130
{
@@ -173,6 +174,7 @@ private void EnableTimer(float pollingIntervalInSeconds)
173174
private void DisableTimer()
174175
{
175176
_pollingIntervalInMilliseconds = 0;
177+
_nextPollingTimeStamp = DateTime.MaxValue;
176178
s_counterGroupEnabledList?.Remove(this);
177179
}
178180

@@ -235,11 +237,14 @@ private void OnTimer()
235237

236238
lock (s_counterGroupLock)
237239
{
238-
_timeStampSinceCollectionStarted = now;
239-
do
240+
if (_eventSource.IsEnabled())
240241
{
241-
_nextPollingTimeStamp += new TimeSpan(0, 0, 0, 0, _pollingIntervalInMilliseconds);
242-
} while (_nextPollingTimeStamp <= now);
242+
_timeStampSinceCollectionStarted = now;
243+
do
244+
{
245+
_nextPollingTimeStamp += new TimeSpan(0, 0, 0, 0, _pollingIntervalInMilliseconds);
246+
} while (_nextPollingTimeStamp <= now);
247+
}
243248
}
244249
}
245250
}
+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
#if USE_MDT_EVENTSOURCE
5+
using Microsoft.Diagnostics.Tracing;
6+
#else
7+
using System.Diagnostics.Tracing;
8+
#endif
9+
using System;
10+
using System.Collections.Generic;
11+
using System.Threading;
12+
using System.Threading.Tasks;
13+
using System.Diagnostics;
14+
15+
namespace gh53564Tests
16+
{
17+
public class RuntimeCounterListener : EventListener
18+
{
19+
public RuntimeCounterListener(){}
20+
21+
private DateTime? setToZeroTimestamp = null;
22+
private DateTime? mostRecentTimestamp = null;
23+
public ManualResetEvent ReadyToVerify { get; } = new ManualResetEvent(initialState: false);
24+
25+
protected override void OnEventSourceCreated(EventSource source)
26+
{
27+
if (source.Name.Equals("System.Runtime"))
28+
{
29+
Dictionary<string, string> refreshInterval = new Dictionary<string, string>();
30+
31+
Console.WriteLine($"[{DateTime.Now:hh:mm:ss.fff}] Setting interval to 1");
32+
// first set interval to 1 seconds
33+
refreshInterval["EventCounterIntervalSec"] = "1";
34+
EnableEvents(source, EventLevel.Informational, (EventKeywords)(-1), refreshInterval);
35+
36+
// wait a moment to get some events
37+
Thread.Sleep(TimeSpan.FromSeconds(3));
38+
39+
// then set interval to 0
40+
Console.WriteLine($"[{DateTime.Now:hh:mm:ss.fff}] Setting interval to 0");
41+
refreshInterval["EventCounterIntervalSec"] = "0";
42+
EnableEvents(source, EventLevel.Informational, (EventKeywords)(-1), refreshInterval);
43+
setToZeroTimestamp = DateTime.Now + TimeSpan.FromSeconds(1); // Stash timestamp 1 second after setting to 0
44+
45+
// then attempt to set interval back to 1
46+
Thread.Sleep(TimeSpan.FromSeconds(3));
47+
Console.WriteLine($"[{DateTime.Now:hh:mm:ss.fff}] Setting interval to 1");
48+
refreshInterval["EventCounterIntervalSec"] = "1";
49+
EnableEvents(source, EventLevel.Informational, (EventKeywords)(-1), refreshInterval);
50+
Thread.Sleep(TimeSpan.FromSeconds(3));
51+
Console.WriteLine($"[{DateTime.Now:hh:mm:ss.fff}] Setting ReadyToVerify");
52+
ReadyToVerify.Set();
53+
}
54+
}
55+
56+
protected override void OnEventWritten(EventWrittenEventArgs eventData)
57+
{
58+
mostRecentTimestamp = eventData.TimeStamp;
59+
}
60+
61+
public bool Verify()
62+
{
63+
if (!ReadyToVerify.WaitOne(0))
64+
return false;
65+
66+
return (setToZeroTimestamp is null || mostRecentTimestamp is null) ? false : setToZeroTimestamp < mostRecentTimestamp;
67+
}
68+
}
69+
70+
public partial class TestRuntimeEventCounter
71+
{
72+
public static int Main(string[] args)
73+
{
74+
// Create an EventListener.
75+
using (RuntimeCounterListener myListener = new RuntimeCounterListener())
76+
{
77+
if (myListener.ReadyToVerify.WaitOne(TimeSpan.FromSeconds(15)))
78+
{
79+
Console.WriteLine($"[{DateTime.Now:hh:mm:ss.fff}] Ready to verify");
80+
if (myListener.Verify())
81+
{
82+
Console.WriteLine("Test passed");
83+
return 100;
84+
}
85+
else
86+
{
87+
Console.WriteLine($"Test Failed - did not see one or more of the expected runtime counters.");
88+
return 1;
89+
}
90+
}
91+
else
92+
{
93+
Console.WriteLine("Test Failed - timed out waiting for reset");
94+
return 1;
95+
}
96+
}
97+
}
98+
}
99+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<CLRTestKind>BuildAndRun</CLRTestKind>
5+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
6+
<CLRTestPriority>0</CLRTestPriority>
7+
<GCStressIncompatible>true</GCStressIncompatible>
8+
<!-- This test is timing sensitive and JIT timing affects the results of the test -->
9+
<JitOptimizationSensitive>true</JitOptimizationSensitive>
10+
<!-- This test has a secondary thread with an infinite loop -->
11+
<UnloadabilityIncompatible>true</UnloadabilityIncompatible>
12+
</PropertyGroup>
13+
<ItemGroup>
14+
<Compile Include="gh53564.cs" />
15+
<ProjectReference Include="../common/common.csproj" />
16+
</ItemGroup>
17+
</Project>

0 commit comments

Comments
 (0)