@@ -749,6 +749,25 @@ private unsafe TraceLog(TraceEventDispatcher source)
749749 rawEventSourceToConvert = source ;
750750 SetupCallbacks ( rawEventSourceToConvert ) ;
751751 rawEventSourceToConvert . unhandledEventTemplate . traceEventSource = this ; // Make everything point to the log as its source.
752+
753+ // Self describing metadata doesn't make it to realTimeSource because TraceLog overwrites the event's extended data.
754+ // To address this, we use the event from the raw source, which contains the metadata,
755+ // and convert it to a template that can be registered with realTimeSource.
756+ realTimeSource . RegisterUnhandledEventImpl ( te =>
757+ {
758+ var toSend = realTimeEvent ;
759+ if ( toSend == null )
760+ {
761+ return false ;
762+ }
763+ if ( toSend . containsSelfDescribingMetadata )
764+ {
765+ var template = toSend . CloneToTemplate ( ) ;
766+ realTimeSource . Dynamic . OnNewEventDefintion ( template , true ) ;
767+ return true ;
768+ }
769+ return false ;
770+ } ) ;
752771 }
753772
754773 private unsafe void onAllEventsRealTime ( TraceEvent data )
@@ -813,24 +832,20 @@ private static void RemoveAllButLastEntries<T>(ref GrowableArray<T> growableArra
813832 /// </summary>
814833 private unsafe void DispatchClonedEvent ( TraceEvent toSend )
815834 {
816- // Self describing metadata doesn't make it to realTimeSource because TraceLog overwrites the event's extended data.
817- // To address this, we use the event from the raw source, which contains the metadata,
818- // and convert it to a template that can be registered with realTimeSource.
819- realTimeSource . RegisterUnhandledEventImpl ( te =>
835+ realTimeEvent = toSend ;
836+ TraceEvent eventInRealTimeSource = null ;
837+ try
820838 {
821- if ( toSend . containsSelfDescribingMetadata )
822- {
823- var template = toSend . CloneToTemplate ( ) ;
824- realTimeSource . Dynamic . OnNewEventDefintion ( template , true ) ;
825- return true ;
826- }
827- return false ;
828- } ) ;
829- TraceEvent eventInRealTimeSource = realTimeSource . Lookup ( toSend . eventRecord ) ;
830- eventInRealTimeSource . userData = toSend . userData ;
831- eventInRealTimeSource . eventIndex = toSend . eventIndex ; // Lookup assigns the EventIndex, but we want to keep the original.
832- eventInRealTimeSource . myBuffer = toSend . myBuffer ;
833- realTimeSource . Dispatch ( eventInRealTimeSource ) ;
839+ eventInRealTimeSource = realTimeSource . Lookup ( toSend . eventRecord ) ;
840+ eventInRealTimeSource . userData = toSend . userData ;
841+ eventInRealTimeSource . eventIndex = toSend . eventIndex ; // Lookup assigns the EventIndex, but we want to keep the original.
842+ eventInRealTimeSource . myBuffer = toSend . myBuffer ;
843+ realTimeSource . Dispatch ( eventInRealTimeSource ) ;
844+ }
845+ finally
846+ {
847+ realTimeEvent = null ;
848+ }
834849
835850 // Optimization, remove 'toSend' from the finalization queue.
836851 Debug . Assert ( toSend . myBuffer != IntPtr . Zero ) ;
@@ -4445,6 +4460,7 @@ private struct QueueEntry
44454460
44464461 internal TraceLogEventSource realTimeSource ; // used to call back in real time case.
44474462 private Queue < QueueEntry > realTimeQueue ; // We have to wait a bit to hook up stacks, so we put real time entries in the queue
4463+ private TraceEvent realTimeEvent ; // The current event being processed.
44484464
44494465 // These can ONLY be accessed by the thread calling RealTimeEventSource.Process();
44504466 private Timer realTimeFlushTimer ; // Ensures the queue gets flushed even if there are no incoming events.
0 commit comments