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

Commit

Permalink
Fix EventSource Test Failures in CoreFX (#16999)
Browse files Browse the repository at this point in the history
  • Loading branch information
brianrob authored Mar 17, 2018
1 parent 828c6c3 commit 8a5464f
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 47 deletions.
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

0 comments on commit 8a5464f

Please sign in to comment.