Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 80 additions & 16 deletions src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1649,6 +1649,14 @@ private static uint Rol30(uint input)

private static Guid GenerateGuidFromName(string name)
{
if (namespaceBytes == null)
{
namespaceBytes = new byte[] {
0x48, 0x2C, 0x2D, 0xB2, 0xC3, 0x90, 0x47, 0xC8,
0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1, 0x30, 0xFB,
};
}

byte[] bytes = Encoding.BigEndianUnicode.GetBytes(name);
var hash = new Sha1ForNonSecretPurposes();
hash.Start();
Expand Down Expand Up @@ -3734,11 +3742,12 @@ private bool SelfDescribingEvents
internal const string s_ActivityStartSuffix = "Start";
internal const string s_ActivityStopSuffix = "Stop";

// WARNING: Do not depend upon initialized statics during creation of EventSources, as it is possible for creation of an EventSource to trigger
// creation of yet another EventSource. When this happens, these statics may not yet be initialized.
// Rather than depending on initialized statics, use lazy initialization to ensure that the statics are initialized exactly when they are needed.

// used for generating GUID from eventsource name
private static readonly byte[] namespaceBytes = new byte[] {
0x48, 0x2C, 0x2D, 0xB2, 0xC3, 0x90, 0x47, 0xC8,
0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1, 0x30, 0xFB,
};
private static byte[] namespaceBytes;

#endregion
}
Expand Down Expand Up @@ -3847,6 +3856,16 @@ public event EventHandler<EventSourceCreatedEventArgs> EventSourceCreated
/// </summary>
public event EventHandler<EventWrittenEventArgs> EventWritten;

static EventListener()
{
#if FEATURE_PERFTRACING
// Ensure that RuntimeEventSource is initialized so that EventListeners get an opportunity to subscribe to its events.
// This is required because RuntimeEventSource never emit events on its own, and thus will never be initialized
// in the normal way that EventSources are initialized.
GC.KeepAlive(RuntimeEventSource.Log);
#endif // FEATURE_PERFTRACING
}

/// <summary>
/// Create a new EventListener in which all events start off turned off (use EnableEvents to turn
/// them on).
Expand Down Expand Up @@ -4082,9 +4101,24 @@ internal static void AddEventSource(EventSource newEventSource)
}
newEventSource.m_id = newIndex;

// Add every existing dispatcher to the new EventSource
for (EventListener listener = s_Listeners; listener != null; listener = listener.m_Next)
newEventSource.AddListener(listener);
#if DEBUG
// Disable validation of EventSource/EventListener connections in case a call to EventSource.AddListener
// causes a recursive call into this method.
bool previousValue = s_ConnectingEventSourcesAndListener;
s_ConnectingEventSourcesAndListener = true;
try
{
#endif
// Add every existing dispatcher to the new EventSource
for (EventListener listener = s_Listeners; listener != null; listener = listener.m_Next)
newEventSource.AddListener(listener);
#if DEBUG
}
finally
{
s_ConnectingEventSourcesAndListener = previousValue;
}
#endif

Validate();
}
Expand Down Expand Up @@ -4165,6 +4199,14 @@ private static void RemoveReferencesToListenerInEventSources(EventListener liste
[Conditional("DEBUG")]
internal static void Validate()
{
#if DEBUG
// Don't run validation code if we're in the middle of modifying the connections between EventSources and EventListeners.
if (s_ConnectingEventSourcesAndListener)
{
return;
}
#endif

lock (EventListenersLock)
{
// Get all listeners
Expand Down Expand Up @@ -4254,18 +4296,30 @@ private void CallBackForExistingEventSources(bool addToListenersList, EventHandl
// is created.
WeakReference[] eventSourcesSnapshot = s_EventSources.ToArray();

for (int i = 0; i < eventSourcesSnapshot.Length; i++)
#if DEBUG
bool previousValue = s_ConnectingEventSourcesAndListener;
s_ConnectingEventSourcesAndListener = true;
try
{
WeakReference eventSourceRef = eventSourcesSnapshot[i];
EventSource eventSource = eventSourceRef.Target as EventSource;
if (eventSource != null)
#endif
for (int i = 0; i < eventSourcesSnapshot.Length; i++)
{
EventSourceCreatedEventArgs args = new EventSourceCreatedEventArgs();
args.EventSource = eventSource;
callback(this, args);
WeakReference eventSourceRef = eventSourcesSnapshot[i];
EventSource eventSource = eventSourceRef.Target as EventSource;
if (eventSource != null)
{
EventSourceCreatedEventArgs args = new EventSourceCreatedEventArgs();
args.EventSource = eventSource;
callback(this, args);
}
}
#if DEBUG
}

finally
{
s_ConnectingEventSourcesAndListener = previousValue;
}
#endif
Validate();
}
finally
Expand Down Expand Up @@ -4299,6 +4353,16 @@ private void CallBackForExistingEventSources(bool addToListenersList, EventHandl
/// </summary>
private static bool s_CreatingListener = false;

#if DEBUG
/// <summary>
/// Used to disable validation of EventSource and EventListener connectivity.
/// This is needed when an EventListener is in the middle of being published to all EventSources
/// and another EventSource is created as part of the process.
/// </summary>
[ThreadStatic]
private static bool s_ConnectingEventSourcesAndListener = false;
#endif

/// <summary>
/// Used to register AD/Process shutdown callbacks.
/// </summary>
Expand Down Expand Up @@ -4637,7 +4701,7 @@ public DateTime TimeStamp
internal set;
}

#region private
#region private
internal EventWrittenEventArgs(EventSource eventSource)
{
m_eventSource = eventSource;
Expand Down
52 changes: 0 additions & 52 deletions tests/src/tracing/common/RuntimeEventSource.cs

This file was deleted.

1 change: 0 additions & 1 deletion tests/src/tracing/common/common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
<Compile Include="Assert.cs" />
<Compile Include="EtlFile.cs" />
<Compile Include="NetPerfFile.cs" />
<Compile Include="RuntimeEventSource.cs" />
<Compile Include="TraceControl.cs" />
<Compile Include="TraceConfiguration.cs" />
</ItemGroup>
Expand Down
35 changes: 26 additions & 9 deletions tests/src/tracing/runtimeeventsource/RuntimeEventSourceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,16 @@ public sealed class RuntimeEventSourceTest
{
static int Main(string[] args)
{
// Get the RuntimeEventSource.
EventSource eventSource = RuntimeEventSource.Log;

SimpleEventListener.EnableKeywords = (EventKeywords)0;
using (SimpleEventListener noEventsListener = new SimpleEventListener("NoEvents"))
{
// Enable the provider, but not any keywords, so we should get no events as long as no rundown occurs.
noEventsListener.EnableEvents(eventSource, EventLevel.Critical, (EventKeywords)(0));

// Create an EventListener.
SimpleEventListener.EnableKeywords = (EventKeywords)0x4c14fccbd;
using (SimpleEventListener listener = new SimpleEventListener("Simple"))
{
// Trigger the allocator task.
System.Threading.Tasks.Task.Run(new Action(Allocator));

// Enable events.
listener.EnableEvents(eventSource, EventLevel.Verbose, (EventKeywords)(0x4c14fccbd));

// Wait for events.
Thread.Sleep(1000);

Expand Down Expand Up @@ -73,13 +66,37 @@ internal sealed class SimpleEventListener : EventListener
{
private string m_name;

// Keep track of the set of keywords to be enabled.
public static EventKeywords EnableKeywords
{
get;
set;
}

public SimpleEventListener(string name)
{
m_name = name;
}

public int EventCount { get; private set; } = 0;

protected override void OnEventSourceCreated(EventSource eventSource)
{
if (eventSource.Name.Equals("Microsoft-Windows-DotNETRuntime"))
{
if (EnableKeywords != 0)
{
// Enable events.
EnableEvents(eventSource, EventLevel.Verbose, EnableKeywords);
}
else
{
// Enable the provider, but not any keywords, so we should get no events as long as no rundown occurs.
EnableEvents(eventSource, EventLevel.Critical, EnableKeywords);
}
}
}

protected override void OnEventWritten(EventWrittenEventArgs eventData)
{
long osThreadId = -1;
Expand Down