diff options
author | David Mason <davmason@microsoft.com> | 2019-07-09 22:33:24 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-09 22:33:24 -0700 |
commit | d61a380bbfde580986f416d8bf3e687104cd5701 (patch) | |
tree | d0e68c614ddb138ae2cd01a988df07d6bb22b4cc /src/System.Private.CoreLib | |
parent | 27790ab2dbee25d2e9c6fc41863aa7e983552a3f (diff) | |
download | coreclr-d61a380bbfde580986f416d8bf3e687104cd5701.tar.gz coreclr-d61a380bbfde580986f416d8bf3e687104cd5701.tar.bz2 coreclr-d61a380bbfde580986f416d8bf3e687104cd5701.zip |
Let EventPipe threads sleep when no events are available (#25601)
Don't spin forever in EventListener when listening for EventPipe data
Diffstat (limited to 'src/System.Private.CoreLib')
-rw-r--r-- | src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs | 9 | ||||
-rw-r--r-- | src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs | 18 |
2 files changed, 27 insertions, 0 deletions
diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs index f3f48b4583..b50fdadc8c 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Threading; #if FEATURE_PERFTRACING @@ -85,6 +86,11 @@ namespace System.Diagnostics.Tracing NetTrace } + internal sealed class EventPipeWaitHandle : WaitHandle + { + + } + internal sealed class EventPipeConfiguration { private string m_outputFile; @@ -251,6 +257,9 @@ namespace System.Diagnostics.Tracing [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] internal static extern unsafe bool GetNextEvent(UInt64 sessionID, EventPipeEventInstanceData* pInstance); + + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + internal static extern unsafe IntPtr GetWaitHandle(UInt64 sessionID); } } diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs index 4360283247..b4ff7d1b08 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Microsoft.Win32.SafeHandles; namespace System.Diagnostics.Tracing { @@ -32,6 +33,7 @@ namespace System.Diagnostics.Tracing private Int64 m_timeQPCFrequency; private bool m_stopDispatchTask; + private EventPipeWaitHandle m_dispatchTaskWaitHandle = new EventPipeWaitHandle(); private Task? m_dispatchTask = null; private object m_dispatchControlLock = new object(); private Dictionary<EventListener, EventListenerSubscription> m_subscriptions = new Dictionary<EventListener, EventListenerSubscription>(); @@ -42,6 +44,7 @@ namespace System.Diagnostics.Tracing { // Get the ID of the runtime provider so that it can be used as a filter when processing events. m_RuntimeProviderID = EventPipeInternal.GetProvider(NativeRuntimeEventSource.EventSourceName); + m_dispatchTaskWaitHandle.SafeWaitHandle = new SafeWaitHandle(IntPtr.Zero, false); } internal void SendCommand(EventListener eventListener, EventCommand command, bool enable, EventLevel level, EventKeywords matchAnyKeywords) @@ -140,6 +143,9 @@ namespace System.Diagnostics.Tracing if (m_dispatchTask == null) { m_stopDispatchTask = false; + // Create a SafeWaitHandle that won't release the handle when done + m_dispatchTaskWaitHandle.SafeWaitHandle = new SafeWaitHandle(EventPipeInternal.GetWaitHandle(m_sessionID), false); + m_dispatchTask = Task.Factory.StartNew(DispatchEventsToEventListeners, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); } } @@ -151,6 +157,8 @@ namespace System.Diagnostics.Tracing if(m_dispatchTask != null) { m_stopDispatchTask = true; + Debug.Assert(!m_dispatchTaskWaitHandle.SafeWaitHandle.IsInvalid); + Interop.Kernel32.SetEvent(m_dispatchTaskWaitHandle.SafeWaitHandle); m_dispatchTask.Wait(); m_dispatchTask = null; } @@ -163,9 +171,12 @@ namespace System.Diagnostics.Tracing while (!m_stopDispatchTask) { + bool eventsReceived = false; // Get the next event. while (!m_stopDispatchTask && EventPipeInternal.GetNextEvent(m_sessionID, &instanceData)) { + eventsReceived = true; + // Filter based on provider. if (instanceData.ProviderID == m_RuntimeProviderID) { @@ -179,6 +190,13 @@ namespace System.Diagnostics.Tracing // Wait for more events. if (!m_stopDispatchTask) { + if (!eventsReceived) + { + // Future TODO: this would make more sense to handle in EventPipeSession/EventPipe native code. + Debug.Assert(!m_dispatchTaskWaitHandle.SafeWaitHandle.IsInvalid); + m_dispatchTaskWaitHandle.WaitOne(); + } + Thread.Sleep(10); } } |