Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Fix EventSource Test Failures in CoreFX #16999

Merged
merged 5 commits into from
Mar 17, 2018
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
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,7 @@ private unsafe void DefineEventPipeEvents()
continue;

byte[] metadata = EventPipeMetadataGenerator.Instance.GenerateEventMetadata(m_eventData[i]);
uint metadataLength = (metadata != null) ? (uint)metadata.Length : 0;

string eventName = m_eventData[i].Name;
Int64 keywords = m_eventData[i].Descriptor.Keywords;
Expand All @@ -638,7 +639,7 @@ private unsafe void DefineEventPipeEvents()
eventVersion,
level,
pMetadata,
(uint)metadata.Length);
metadataLength);

Debug.Assert(eventHandle != IntPtr.Zero);
m_eventData[i].EventHandle = eventHandle;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using Interlocked = System.Threading.Interlocked;

#if ES_BUILD_STANDALONE
Expand Down Expand Up @@ -42,7 +43,6 @@ internal static void ReserveEventIDsBelow(int eventId)
internal readonly byte[] nameMetadata;

#if FEATURE_PERFTRACING
private IntPtr eventHandle = IntPtr.Zero;
private readonly object eventHandleCreationLock = new object();
#endif

Expand Down Expand Up @@ -82,13 +82,14 @@ private int Compare(string otherName, EventTags otherTags)
}

#if FEATURE_PERFTRACING
public IntPtr GetOrCreateEventHandle(EventProvider provider, EventDescriptor descriptor, TraceLoggingEventTypes eventTypes)
public IntPtr GetOrCreateEventHandle(EventProvider provider, ConcurrentDictionary<int, IntPtr> eventHandleMap, EventDescriptor descriptor, TraceLoggingEventTypes eventTypes)
{
if (eventHandle == IntPtr.Zero)
IntPtr eventHandle = IntPtr.Zero;
if(!eventHandleMap.TryGetValue(descriptor.EventId, out eventHandle))
{
lock (eventHandleCreationLock)
{
if (eventHandle == IntPtr.Zero)
if (!eventHandleMap.TryGetValue(descriptor.EventId, out eventHandle))
{
byte[] metadataBlob = EventPipeMetadataGenerator.Instance.GenerateEventMetadata(
descriptor.EventId,
Expand All @@ -97,6 +98,7 @@ public IntPtr GetOrCreateEventHandle(EventProvider provider, EventDescriptor des
(EventLevel)descriptor.Level,
descriptor.Version,
eventTypes);
uint metadataLength = (metadataBlob != null) ? (uint)metadataBlob.Length : 0;

unsafe
{
Expand All @@ -110,7 +112,7 @@ public IntPtr GetOrCreateEventHandle(EventProvider provider, EventDescriptor des
descriptor.Version,
descriptor.Level,
pMetadataBlob,
(uint)metadataBlob.Length);
metadataLength);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using System.Runtime.InteropServices;
using System.Security;
using System.Collections.ObjectModel;
using System.Collections.Concurrent;

#if !ES_BUILD_AGAINST_DOTNET_V35
using Contract = System.Diagnostics.Contracts.Contract;
Expand All @@ -47,6 +48,10 @@ public partial class EventSource
private byte[] providerMetadata;
#endif

#if FEATURE_PERFTRACING
private ConcurrentDictionary<int, IntPtr> m_eventHandleMap = new ConcurrentDictionary<int, IntPtr>();
#endif

/// <summary>
/// Construct an EventSource with a given name for non-contract based events (e.g. those using the Write() API).
/// </summary>
Expand Down Expand Up @@ -432,7 +437,7 @@ private unsafe void WriteMultiMergeInner(
EventDescriptor descriptor = new EventDescriptor(identity, level, opcode, (long)keywords);

#if FEATURE_PERFTRACING
IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_provider, descriptor, eventTypes);
IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_provider, m_eventHandleMap, descriptor, eventTypes);
Debug.Assert(eventHandle != IntPtr.Zero);
#else
IntPtr eventHandle = IntPtr.Zero;
Expand Down Expand Up @@ -547,7 +552,7 @@ internal unsafe void WriteMultiMerge(
}

#if FEATURE_PERFTRACING
IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_provider, descriptor, eventTypes);
IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_provider, m_eventHandleMap, descriptor, eventTypes);
Debug.Assert(eventHandle != IntPtr.Zero);
#else
IntPtr eventHandle = IntPtr.Zero;
Expand Down Expand Up @@ -616,7 +621,7 @@ private unsafe void WriteImpl(
}

#if FEATURE_PERFTRACING
IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_provider, descriptor, eventTypes);
IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_provider, m_eventHandleMap, descriptor, eventTypes);
Debug.Assert(eventHandle != IntPtr.Zero);
#else
IntPtr eventHandle = IntPtr.Zero;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,48 +65,59 @@ private unsafe byte[] GenerateMetadata(
uint version,
EventParameterInfo[] parameters)
{
// eventID : 4 bytes
// eventName : (eventName.Length + 1) * 2 bytes
// keywords : 8 bytes
// eventVersion : 4 bytes
// level : 4 bytes
// parameterCount : 4 bytes
uint metadataLength = 24 + ((uint)eventName.Length + 1) * 2;

// Check for an empty payload.
// Write<T> calls with no arguments by convention have a parameter of
// type NullTypeInfo which is serialized as nothing.
if((parameters.Length == 1) && (parameters[0].ParameterType == typeof(EmptyStruct)))
byte[] metadata = null;
try
{
parameters = Array.Empty<EventParameterInfo>();
}

// Increase the metadataLength for parameters.
foreach (var parameter in parameters)
{
metadataLength = metadataLength + parameter.GetMetadataLength();
}

byte[] metadata = new byte[metadataLength];

// Write metadata: eventID, eventName, keywords, eventVersion, level, parameterCount, param1 type, param1 name...
fixed (byte *pMetadata = metadata)
{
uint offset = 0;
WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)eventId);
fixed(char *pEventName = eventName)
// eventID : 4 bytes
// eventName : (eventName.Length + 1) * 2 bytes
// keywords : 8 bytes
// eventVersion : 4 bytes
// level : 4 bytes
// parameterCount : 4 bytes
uint metadataLength = 24 + ((uint)eventName.Length + 1) * 2;

// Check for an empty payload.
// Write<T> calls with no arguments by convention have a parameter of
// type NullTypeInfo which is serialized as nothing.
if ((parameters.Length == 1) && (parameters[0].ParameterType == typeof(EmptyStruct)))
{
WriteToBuffer(pMetadata, metadataLength, ref offset, (byte *)pEventName, ((uint)eventName.Length + 1) * 2);
parameters = Array.Empty<EventParameterInfo>();
}
WriteToBuffer(pMetadata, metadataLength, ref offset, keywords);
WriteToBuffer(pMetadata, metadataLength, ref offset, version);
WriteToBuffer(pMetadata, metadataLength, ref offset, level);
WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)parameters.Length);

// Increase the metadataLength for parameters.
foreach (var parameter in parameters)
{
parameter.GenerateMetadata(pMetadata, ref offset, metadataLength);
metadataLength = metadataLength + parameter.GetMetadataLength();
}

metadata = new byte[metadataLength];

// Write metadata: eventID, eventName, keywords, eventVersion, level, parameterCount, param1 type, param1 name...
fixed (byte* pMetadata = metadata)
{
uint offset = 0;
WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)eventId);
fixed (char* pEventName = eventName)
{
WriteToBuffer(pMetadata, metadataLength, ref offset, (byte*)pEventName, ((uint)eventName.Length + 1) * 2);
}
WriteToBuffer(pMetadata, metadataLength, ref offset, keywords);
WriteToBuffer(pMetadata, metadataLength, ref offset, version);
WriteToBuffer(pMetadata, metadataLength, ref offset, level);
WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)parameters.Length);
foreach (var parameter in parameters)
{
parameter.GenerateMetadata(pMetadata, ref offset, metadataLength);
}
Debug.Assert(metadataLength == offset);
}
Debug.Assert(metadataLength == offset);
}
catch
{
// If a failure occurs during metadata generation, make sure that we don't return
// malformed metadata. Instead, return a null metadata blob.
// Consumers can either build in knowledge of the event or skip it entirely.
metadata = null;
}

return metadata;
Expand Down Expand Up @@ -262,7 +273,12 @@ private static unsafe void GenerateMetadataForProperty(PropertyAnalysis property
// TypeCode : 4 bytes
// PropertyName : NULL-terminated string
TypeCode typeCode = GetTypeCodeExtended(property.typeInfo.DataType);
Debug.Assert(typeCode != TypeCode.Object);

// EventPipe does not support this type. Throw, which will cause no metadata to be registered for this event.
if(typeCode == TypeCode.Object)
{
throw new NotSupportedException();
}

// Write the type code.
EventPipeMetadataGenerator.WriteToBuffer(pMetadataBlob, blobSize, ref offset, (uint)typeCode);
Expand Down
1 change: 0 additions & 1 deletion src/vm/eventpipe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -958,7 +958,6 @@ INT_PTR QCALLTYPE EventPipeInternal::DefineEvent(
BEGIN_QCALL;

_ASSERTE(provHandle != NULL);
_ASSERTE(pMetadata != NULL);
EventPipeProvider *pProvider = reinterpret_cast<EventPipeProvider *>(provHandle);
pEvent = pProvider->AddEvent(eventID, keywords, eventVersion, (EventPipeEventLevel)level, (BYTE *)pMetadata, metadataLength);
_ASSERTE(pEvent != NULL);
Expand Down