[EventPipe] Minor bug fixes, and remove redundant/unused code. (#23956)
authorJosé Rivero <jorive@microsoft.com>
Wed, 17 Apr 2019 01:58:31 +0000 (18:58 -0700)
committerGitHub <noreply@github.com>
Wed, 17 Apr 2019 01:58:31 +0000 (18:58 -0700)
- Update MicrosoftDiagnosticsTracingTraceEventPackageVersion
- Delete connection if the request is unknown/unhandled
- Adding missing error handling.
  - Provider names must be defined.
- Some renaming, error handling, and build warnings.
- Removing test code, and merge EventPipe::Enable functions.
- Remove commented/non-used lines.

15 files changed:
dependencies.props
src/debug/debug-pal/win/diagnosticsipc.cpp
src/vm/diagnosticserver.cpp
src/vm/diagnosticserver.h
src/vm/eventpipe.cpp
src/vm/eventpipe.h
src/vm/eventpipeconfiguration.cpp
src/vm/eventpipeinternal.cpp
src/vm/eventpipeinternal.h
src/vm/eventpipeprotocolhelper.cpp
src/vm/eventpipeprotocolhelper.h
src/vm/eventpipesession.cpp
src/vm/eventpipesession.h
src/vm/fastserializer.cpp
src/vm/fastserializer.h

index 351914f..f8f4a92 100644 (file)
@@ -35,7 +35,7 @@
     <MicrosoftNETCoreRuntimeCoreCLRPackageVersion>3.0.0-preview5-27615-71</MicrosoftNETCoreRuntimeCoreCLRPackageVersion>
     <XunitPackageVersion>2.4.1-pre.build.4059</XunitPackageVersion>
     <XunitPerformanceApiPackageVersion>1.0.0-beta-build0015</XunitPerformanceApiPackageVersion>
-    <MicrosoftDiagnosticsTracingTraceEventPackageVersion>2.0.36</MicrosoftDiagnosticsTracingTraceEventPackageVersion>
+    <MicrosoftDiagnosticsTracingTraceEventPackageVersion>2.0.40</MicrosoftDiagnosticsTracingTraceEventPackageVersion>
     <IbcMergePackageVersion>4.6.0-alpha-00001</IbcMergePackageVersion>
     <CommandLineParserVersion>2.2.0</CommandLineParserVersion>
 
index 5467581..ef65f23 100644 (file)
@@ -73,7 +73,7 @@ IpcStream *IpcStream::DiagnosticsIpc::Accept(ErrorCallback callback) const
     return new IpcStream(hPipe);
 }
 
-void IpcStream::DiagnosticsIpc::Unlink(ErrorCallback callback)
+void IpcStream::DiagnosticsIpc::Unlink(ErrorCallback)
 {
 }
 
index 81cdc25..4ce0131 100644 (file)
@@ -57,20 +57,17 @@ static DWORD WINAPI DiagnosticsServerThread(LPVOID lpThreadParameter)
 
             switch (header.RequestType)
             {
-            case DiagnosticMessageType::EnableEventPipe:
-                EventPipeProtocolHelper::EnableFileTracingEventHandler(pStream);
+            case DiagnosticMessageType::StopEventPipeTracing:
+                EventPipeProtocolHelper::StopTracing(pStream);
                 break;
 
-            case DiagnosticMessageType::DisableEventPipe:
-                EventPipeProtocolHelper::DisableFileTracingEventHandler(pStream);
-                break;
-
-            case DiagnosticMessageType::StreamEventPipe:
-                EventPipeProtocolHelper::AttachTracingEventHandler(pStream);
+            case DiagnosticMessageType::CollectEventPipeTracing:
+                EventPipeProtocolHelper::CollectTracing(pStream);
                 break;
 
             default:
-                LOG((LF_DIAGNOSTICS_PORT, LL_WARNING, "Received unknow request type (%d)\n", header.RequestType));
+                STRESS_LOG1(LF_DIAGNOSTICS_PORT, LL_WARNING, "Received unknown request type (%d)\n", header.RequestType);
+                delete pStream;
                 break;
             }
         }
index 76ad3ef..c3c2ca4 100644 (file)
@@ -18,11 +18,9 @@ enum class DiagnosticMessageType : uint32_t
 
     ///////////////////////////////////////////////////////////////////////////
     // EventPipe
-    EnableEventPipe = 1024,
-    DisableEventPipe,
-    StreamEventPipe,
-    AttachEventPipe,
-    DetachEventPipe,
+    StartEventPipeTracing = 1024, // To file
+    StopEventPipeTracing,
+    CollectEventPipeTracing, // To IPC
 
     ///////////////////////////////////////////////////////////////////////////
     // Profiler = 2048
index b730bd8..dc94c2b 100644 (file)
@@ -236,14 +236,18 @@ EventPipeSessionID EventPipe::Enable(
     uint32_t circularBufferSizeInMB,
     uint64_t profilerSamplingRateInNanoseconds,
     const EventPipeProviderConfiguration *pProviders,
-    uint32_t numProviders)
+    uint32_t numProviders,
+    EventPipeSessionType sessionType,
+    IpcStream *const pStream)
 {
     CONTRACTL
     {
         THROWS;
         GC_TRIGGERS;
         MODE_ANY;
-        PRECONDITION((numProviders == 0) || (numProviders > 0 && pProviders != nullptr));
+        PRECONDITION(circularBufferSizeInMB > 0);
+        PRECONDITION(profilerSamplingRateInNanoseconds > 0);
+        PRECONDITION(numProviders > 0 && pProviders != nullptr);
     }
     CONTRACTL_END;
 
@@ -251,83 +255,22 @@ EventPipeSessionID EventPipe::Enable(
     CrstHolder _crst(GetLock());
 
     // Create a new session.
-    SampleProfiler::SetSamplingRate((unsigned long)profilerSamplingRateInNanoseconds);
+    SampleProfiler::SetSamplingRate(static_cast<unsigned long>(profilerSamplingRateInNanoseconds));
     EventPipeSession *pSession = s_pConfig->CreateSession(
-        (strOutputPath != nullptr) ? EventPipeSessionType::File : EventPipeSessionType::Streaming,
+        sessionType,
         circularBufferSizeInMB,
         pProviders,
         numProviders);
 
-    // Initialize the last file switch time.
-    s_lastFlushSwitchTime = CLRGetTickCount64();
-
-    // Create the event pipe file.
-    // A NULL output path means that we should not write the results to a file.
-    // This is used in the EventListener streaming case.
-    if (strOutputPath != NULL)
-        s_pFile = new EventPipeFile(new FileStreamWriter(SString(strOutputPath)));
-    return Enable(pSession);
-}
-
-EventPipeSessionID EventPipe::Enable(
-    IpcStream *pStream,
-    uint32_t circularBufferSizeInMB,
-    uint64_t profilerSamplingRateInNanoseconds,
-    const EventPipeProviderConfiguration *pProviders,
-    uint32_t numProviders)
-{
-    CONTRACTL
-    {
-        THROWS;
-        GC_TRIGGERS;
-        MODE_ANY;
-        PRECONDITION(pStream != nullptr);
-        PRECONDITION((numProviders == 0) || (numProviders > 0 && pProviders != nullptr));
-    }
-    CONTRACTL_END;
-
-    if (numProviders == 0 || pProviders == nullptr)
-        return (EventPipeSessionID) nullptr;
-
-    // Take the lock before enabling tracing.
-    CrstHolder _crst(GetLock());
-
-    // Create a new session.
-    SampleProfiler::SetSamplingRate((unsigned long)profilerSamplingRateInNanoseconds);
-    EventPipeSession *pSession = s_pConfig->CreateSession(
-        EventPipeSessionType::IpcStream,
-        circularBufferSizeInMB,
-        pProviders,
-        numProviders);
-
-    // Initialize the last file switch time.
-    s_lastFlushSwitchTime = CLRGetTickCount64();
-
-    // Reply back to client with the SessionId
-    uint32_t nBytesWritten = 0;
-    EventPipeSessionID sessionId = (EventPipeSessionID) pSession;
-    bool fSuccess = pStream->Write(&sessionId, sizeof(sessionId), nBytesWritten);
-    if (!fSuccess)
-    {
-        // TODO: Add error handling.
-        s_pConfig->DeleteSession(pSession);
-
-        delete pStream;
-        return (EventPipeSessionID) nullptr;
-    }
-
-    s_pFile = new EventPipeFile(new IpcStreamWriter(pStream));
-
-    // Enable the session.
-    const DWORD FlushTimerPeriodMS = 100; // TODO: Define a good number here for streaming.
-    return Enable(pSession, FlushTimer, FlushTimerPeriodMS, FlushTimerPeriodMS);
+    EventPipeSessionID sessionId = Enable(strOutputPath, pSession, sessionType, pStream);
+    return sessionId;
 }
 
 EventPipeSessionID EventPipe::Enable(
+    LPCWSTR strOutputPath,
     EventPipeSession *const pSession,
-    WAITORTIMERCALLBACK callback,
-    DWORD dueTime,
-    DWORD period)
+    EventPipeSessionType sessionType,
+    IpcStream *const pStream)
 {
     CONTRACTL
     {
@@ -339,12 +282,16 @@ EventPipeSessionID EventPipe::Enable(
     }
     CONTRACTL_END;
 
-    // If tracing is not initialized or is already enabled, bail here.
-    if (!s_tracingInitialized || s_pConfig == nullptr || s_pConfig->Enabled())
+    // If the state or arguments are invalid, bail here.
+    if (pSession == nullptr || !pSession->IsValid())
+        return 0;
+    if (sessionType == EventPipeSessionType::File && strOutputPath == nullptr)
+        return 0;
+    if (sessionType == EventPipeSessionType::IpcStream && pStream == nullptr)
         return 0;
 
-    // If the state or arguments are invalid, bail here.
-    if (pSession == NULL || !pSession->IsValid())
+    // If tracing is not initialized or is already enabled, bail here.
+    if (!s_tracingInitialized || s_pConfig == nullptr || s_pConfig->Enabled())
         return 0;
 
     // Enable the EventPipe EventSource.
@@ -352,6 +299,27 @@ EventPipeSessionID EventPipe::Enable(
 
     // Save the session.
     s_pSession = pSession;
+    EventPipeSessionID sessionId = reinterpret_cast<EventPipeSessionID>(s_pSession);
+
+    // Create the event pipe file.
+    // A NULL output path means that we should not write the results to a file.
+    // This is used in the EventListener streaming case.
+    switch (sessionType)
+    {
+        case EventPipeSessionType::File:
+            if (strOutputPath != nullptr)
+                s_pFile = new EventPipeFile(new FileStreamWriter(SString(strOutputPath)));
+            break;
+
+        case EventPipeSessionType::IpcStream:
+            s_pFile = new EventPipeFile(new IpcStreamWriter(sessionId, pStream));
+            CreateFlushTimerCallback();
+            break;
+
+        default:
+            s_pFile = nullptr;
+            break;
+    }
 
     // Enable tracing.
     s_pConfig->Enable(s_pSession);
@@ -359,11 +327,8 @@ EventPipeSessionID EventPipe::Enable(
     // Enable the sample profiler
     SampleProfiler::Enable();
 
-    if (callback != nullptr)
-        CreateFlushTimerCallback(callback, dueTime, period);
-
     // Return the session ID.
-    return (EventPipeSessionID)s_pSession;
+    return sessionId;
 }
 
 void EventPipe::Disable(EventPipeSessionID id)
@@ -459,16 +424,13 @@ void EventPipe::Disable(EventPipeSessionID id)
     }
 }
 
-void EventPipe::CreateFlushTimerCallback(WAITORTIMERCALLBACK callback, DWORD dueTime, DWORD period)
+void EventPipe::CreateFlushTimerCallback()
 {
     CONTRACTL
     {
         THROWS;
         GC_TRIGGERS;
         MODE_ANY;
-        PRECONDITION(callback != nullptr);
-        PRECONDITION(dueTime > 0);
-        PRECONDITION(period > 0);
         PRECONDITION(GetLock()->OwnedByCurrentThread());
     }
     CONTRACTL_END
@@ -482,16 +444,19 @@ void EventPipe::CreateFlushTimerCallback(WAITORTIMERCALLBACK callback, DWORD due
 
     timerContextHolder->TimerId = 0;
 
+    // Initialize the last file switch time.
+    s_lastFlushSwitchTime = CLRGetTickCount64();
+
     bool success = false;
     _ASSERTE(s_fileSwitchTimerHandle == NULL);
     EX_TRY
     {
         if (ThreadpoolMgr::CreateTimerQueueTimer(
                 &s_fileSwitchTimerHandle,
-                callback,
+                FlushTimer,
                 timerContextHolder,
-                dueTime,
-                period,
+                100, // DueTime (msec)
+                100, // Period (msec)
                 0 /* flags */))
         {
             _ASSERTE(s_fileSwitchTimerHandle != NULL);
index e60c493..e3704d7 100644 (file)
@@ -21,6 +21,7 @@ class MethodDesc;
 struct EventPipeProviderConfiguration;
 class EventPipeSession;
 class IpcStream;
+enum class EventPipeSessionType;
 
 // EVENT_FILTER_DESCRIPTOR (This type does not exist on non-Windows platforms.)
 //  https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/ns-evntprov-_event_filter_descriptor
@@ -28,6 +29,7 @@ class IpcStream;
 //  determines which events are reported and traced. The structure gives the
 //  event provider greater control over the selection of events for reporting
 //  and tracing.
+// TODO: EventFilterDescriptor and EventData (defined below) are the same.
 struct EventFilterDescriptor
 {
     // A pointer to the filter data.
@@ -231,7 +233,6 @@ public:
 };
 
 typedef UINT64 EventPipeSessionID;
-typedef void (*FlushTimerCallback)();
 
 class EventPipe
 {
@@ -255,14 +256,9 @@ public:
         uint32_t circularBufferSizeInMB,
         uint64_t profilerSamplingRateInNanoseconds,
         const EventPipeProviderConfiguration *pProviders,
-        uint32_t numProviders);
-
-    static EventPipeSessionID Enable(
-        IpcStream *pStream,
-        uint32_t circularBufferSizeInMB,
-        uint64_t profilerSamplingRateInNanoseconds,
-        const EventPipeProviderConfiguration *pProviders,
-        uint32_t numProviders);
+        uint32_t numProviders,
+        EventPipeSessionType sessionType,
+        IpcStream *const pStream);
 
     // Disable tracing via the event pipe.
     static void Disable(EventPipeSessionID id);
@@ -311,12 +307,12 @@ private:
 
     // Enable the specified EventPipe session.
     static EventPipeSessionID Enable(
+        LPCWSTR strOutputPath,
         EventPipeSession *const pSession,
-        WAITORTIMERCALLBACK callback = nullptr,
-        DWORD dueTime = 0,
-        DWORD period = 0);
+        EventPipeSessionType sessionType,
+        IpcStream *const pStream);
 
-    static void CreateFlushTimerCallback(WAITORTIMERCALLBACK Callback, DWORD DueTime, DWORD Period);
+    static void CreateFlushTimerCallback();
 
     static void DeleteFlushTimerCallback();
 
index 48899df..9c7d396 100644 (file)
@@ -319,7 +319,8 @@ EventPipeSession *EventPipeConfiguration::CreateSession(
         THROWS;
         GC_NOTRIGGER;
         MODE_ANY;
-        PRECONDITION((numProviders == 0) || (numProviders > 0 && pProviders != nullptr));
+        PRECONDITION(circularBufferSizeInMB > 0);
+        PRECONDITION(numProviders > 0 && pProviders != nullptr);
     }
     CONTRACTL_END;
 
index 17efeb3..9291d6b 100644 (file)
@@ -20,7 +20,7 @@
 UINT64 QCALLTYPE EventPipeInternal::Enable(
     __in_z LPCWSTR outputFile,
     UINT32 circularBufferSizeInMB,
-    INT64 profilerSamplingRateInNanoseconds,
+    UINT64 profilerSamplingRateInNanoseconds,
     EventPipeProviderConfiguration *pProviders,
     UINT32 numProviders)
 {
@@ -28,6 +28,15 @@ UINT64 QCALLTYPE EventPipeInternal::Enable(
 
     UINT64 sessionID = 0;
 
+    // Invalid input!
+    if (circularBufferSizeInMB == 0 ||
+        profilerSamplingRateInNanoseconds == 0 ||
+        numProviders == 0 ||
+        pProviders == nullptr)
+    {
+        return 0;
+    }
+
     BEGIN_QCALL;
     {
         sessionID = EventPipe::Enable(
@@ -35,7 +44,9 @@ UINT64 QCALLTYPE EventPipeInternal::Enable(
             circularBufferSizeInMB,
             profilerSamplingRateInNanoseconds,
             pProviders,
-            numProviders);
+            numProviders,
+            outputFile != NULL ? EventPipeSessionType::File : EventPipeSessionType::Streaming,
+            nullptr);
     }
     END_QCALL;
 
index e4252c7..97178c0 100644 (file)
@@ -47,12 +47,10 @@ public:
     static UINT64 QCALLTYPE Enable(
         __in_z LPCWSTR outputFile,
         UINT32 circularBufferSizeInMB,
-        INT64 profilerSamplingRateInNanoseconds,
+        UINT64 profilerSamplingRateInNanoseconds,
         EventPipeProviderConfiguration *pProviders,
         UINT32 numProviders);
 
-    //! TODO: Add a ListActiveSessions to get the live SessionID in order to Disable?
-
     //!
     //! Disables the specified session Id.
     //!
index 24eb2b0..8217dae 100644 (file)
@@ -3,12 +3,29 @@
 // See the LICENSE file in the project root for more information.
 
 #include "common.h"
+#include "fastserializer.h"
+#include "eventpipefile.h"
 #include "eventpipeprotocolhelper.h"
+#include "eventpipesession.h"
 #include "diagnosticsipc.h"
 #include "diagnosticsprotocol.h"
 
 #ifdef FEATURE_PERFTRACING
 
+static bool IsNullOrWhiteSpace(LPCWSTR value)
+{
+    if (value == nullptr)
+        return true;
+
+    while (*value)
+    {
+        if (!iswspace(*value))
+            return false;
+        ++value;
+    }
+    return true;
+}
+
 bool EventPipeProtocolHelper::TryParseProviderConfiguration(uint8_t *&bufferCursor, uint32_t &bufferLen, CQuickArray<EventPipeProviderConfiguration> &result)
 {
     // Picking an arbitrary upper bound,
@@ -39,93 +56,18 @@ bool EventPipeProtocolHelper::TryParseProviderConfiguration(uint8_t *&bufferCurs
         LPCWSTR pProviderName = nullptr;
         if (!TryParseString(bufferCursor, bufferLen, pProviderName))
             return false;
-        if (wcslen(pProviderName) == 0)
-            return false; // TODO: Should we ignore these input?
+        if (IsNullOrWhiteSpace(pProviderName))
+            return false;
 
         LPCWSTR pFilterData = nullptr; // This parameter is optional.
         TryParseString(bufferCursor, bufferLen, pFilterData);
 
         pConfigs[i] = EventPipeProviderConfiguration(pProviderName, keywords, logLevel, pFilterData);
     }
-    return true;
+    return (countConfigs > 0);
 }
 
-void EventPipeProtocolHelper::EnableFileTracingEventHandler(IpcStream *pStream)
-{
-    CONTRACTL
-    {
-        THROWS;
-        GC_TRIGGERS;
-        MODE_ANY;
-        PRECONDITION(pStream != nullptr);
-    }
-    CONTRACTL_END;
-
-    // TODO: Read within a loop.
-    uint8_t buffer[IpcStreamReadBufferSize]{};
-    uint32_t nNumberOfBytesRead = 0;
-    bool fSuccess = pStream->Read(buffer, sizeof(buffer), nNumberOfBytesRead);
-    if (!fSuccess)
-    {
-        // TODO: Add error handling.
-        delete pStream;
-        return;
-    }
-
-    // The protocol buffer is defined as:
-    // X, Y, Z means encode bytes for X followed by bytes for Y followed by bytes for Z
-    // message = uint circularBufferMB, string outputPath, array<provider_config> providers
-    // uint = 4 little endian bytes
-    // ulong = 8 little endian bytes
-    // wchar = 2 little endian bytes, UTF16 encoding
-    // array<T> = uint length, length # of Ts
-    // string = (array<char> where the last char must = 0) or (length = 0)
-    // provider_config = ulong keywords, uint logLevel, string provider_name, string filter_data
-
-    LPCWSTR strOutputPath;
-    uint32_t circularBufferSizeInMB = EventPipeProtocolHelper::DefaultCircularBufferMB;
-    CQuickArray<EventPipeProviderConfiguration> providerConfigs;
-
-    uint8_t *pBufferCursor = buffer;
-    uint32_t bufferLen = nNumberOfBytesRead;
-    if (!TryParse(pBufferCursor, bufferLen, circularBufferSizeInMB) ||
-        !TryParseString(pBufferCursor, bufferLen, strOutputPath) ||
-        !TryParseProviderConfiguration(pBufferCursor, bufferLen, providerConfigs))
-    {
-        // TODO: error handling
-        delete pStream;
-        return;
-    }
-
-    EventPipeSessionID sessionId = (EventPipeSessionID) nullptr;
-    if (providerConfigs.Size() > 0)
-    {
-        sessionId = EventPipe::Enable(
-            strOutputPath,                                  // outputFile
-            circularBufferSizeInMB,                         // circularBufferSizeInMB
-            DefaultProfilerSamplingRateInNanoseconds,       // ProfilerSamplingRateInNanoseconds
-            providerConfigs.Ptr(),                          // pConfigs
-            static_cast<uint32_t>(providerConfigs.Size())); // numConfigs
-    }
-
-    uint32_t nBytesWritten = 0;
-    fSuccess = pStream->Write(&sessionId, sizeof(sessionId), nBytesWritten);
-    if (!fSuccess)
-    {
-        // TODO: Add error handling.
-        delete pStream;
-        return;
-    }
-
-    fSuccess = pStream->Flush();
-    if (!fSuccess)
-    {
-        // TODO: Add error handling.
-    }
-    delete pStream;
-}
-
-void EventPipeProtocolHelper::DisableFileTracingEventHandler(IpcStream *pStream)
+void EventPipeProtocolHelper::StopTracing(IpcStream *pStream)
 {
     CONTRACTL
     {
@@ -164,7 +106,13 @@ void EventPipeProtocolHelper::DisableFileTracingEventHandler(IpcStream *pStream)
     delete pStream;
 }
 
-void EventPipeProtocolHelper::AttachTracingEventHandler(IpcStream *pStream)
+static bool TryParseCircularBufferSize(uint8_t *&bufferCursor, uint32_t &bufferLen, uint32_t &circularBufferSizeInMB)
+{
+    const bool CanParse = TryParse(bufferCursor, bufferLen, circularBufferSizeInMB);
+    return CanParse && (circularBufferSizeInMB > 0);
+}
+
+void EventPipeProtocolHelper::CollectTracing(IpcStream *pStream)
 {
     CONTRACTL
     {
@@ -175,6 +123,9 @@ void EventPipeProtocolHelper::AttachTracingEventHandler(IpcStream *pStream)
     }
     CONTRACTL_END;
 
+    if (pStream == nullptr)
+        return;
+
     // TODO: Read within a loop.
     uint8_t buffer[IpcStreamReadBufferSize]{};
     uint32_t nNumberOfBytesRead = 0;
@@ -201,8 +152,8 @@ void EventPipeProtocolHelper::AttachTracingEventHandler(IpcStream *pStream)
 
     uint8_t *pBufferCursor = buffer;
     uint32_t bufferLen = nNumberOfBytesRead;
-    if (!TryParse(pBufferCursor, bufferLen, circularBufferSizeInMB) ||
-        !TryParseString(pBufferCursor, bufferLen, strOutputPath) ||
+    if (!TryParseCircularBufferSize(pBufferCursor, bufferLen, circularBufferSizeInMB) ||
+        !TryParseString(pBufferCursor, bufferLen, strOutputPath) || // TODO: Remove. Currently ignored in this scenario.
         !TryParseProviderConfiguration(pBufferCursor, bufferLen, providerConfigs))
     {
         // TODO: error handling
@@ -210,15 +161,17 @@ void EventPipeProtocolHelper::AttachTracingEventHandler(IpcStream *pStream)
         return;
     }
 
-    if (providerConfigs.Size() > 0)
-    {
-        EventPipe::Enable(
-            pStream,                                        // IPC stream
-            circularBufferSizeInMB,                         // circularBufferSizeInMB
-            DefaultProfilerSamplingRateInNanoseconds,       // ProfilerSamplingRateInNanoseconds
-            providerConfigs.Ptr(),                          // pConfigs
-            static_cast<uint32_t>(providerConfigs.Size())); // numConfigs
-    }
+    auto sessionId = EventPipe::Enable(
+        nullptr,                                        // strOutputPath (ignored in this scenario)
+        circularBufferSizeInMB,                         // circularBufferSizeInMB
+        DefaultProfilerSamplingRateInNanoseconds,       // ProfilerSamplingRateInNanoseconds
+        providerConfigs.Ptr(),                          // pConfigs
+        static_cast<uint32_t>(providerConfigs.Size()),  // numConfigs
+        EventPipeSessionType::IpcStream,                // EventPipeSessionType
+        pStream);                                       // IpcStream
+
+    if (sessionId == 0)
+        delete pStream;
 }
 
 #endif // FEATURE_PERFTRACING
index 4fc8580..8832521 100644 (file)
@@ -16,10 +16,8 @@ class EventPipeProtocolHelper
 {
 public:
     // IPC event handlers.
-    static void EnableFileTracingEventHandler(IpcStream *pStream);
-    static void DisableFileTracingEventHandler(IpcStream *pStream);
-
-    static void AttachTracingEventHandler(IpcStream *pStream);
+    static void StopTracing(IpcStream *pStream);
+    static void CollectTracing(IpcStream *pStream); // `dotnet-trace collect`
 
 private:
     const static uint32_t DefaultCircularBufferMB = 1024; // 1 GB
index 30c88fb..ef71818 100644 (file)
@@ -21,7 +21,8 @@ EventPipeSession::EventPipeSession(
         THROWS;
         GC_NOTRIGGER;
         MODE_ANY;
-        PRECONDITION((numProviders == 0) || (numProviders > 0 && pProviders != nullptr));
+        PRECONDITION(circularBufferSizeInMB > 0);
+        PRECONDITION(numProviders > 0 && pProviders != nullptr);
     }
     CONTRACTL_END;
 
index 128ba77..829e18b 100644 (file)
@@ -12,9 +12,9 @@ class EventPipeSessionProvider;
 
 enum class EventPipeSessionType
 {
-    File,
-    Streaming,
-    IpcStream
+    File,       // EventToFile
+    Streaming,  // EventToEventListener
+    IpcStream   // EventToIpc
 };
 
 class EventPipeSession
index 0b2c0f6..620b510 100644 (file)
@@ -12,7 +12,7 @@
 // As a result of work on V3 of Event Pipe (https://github.com/Microsoft/perfview/pull/532) it got removed
 // if you need it, please use git to restore it
 
-IpcStreamWriter::IpcStreamWriter(IpcStream *pStream) : _pStream(pStream)
+IpcStreamWriter::IpcStreamWriter(uint64_t id, IpcStream *pStream) : _pStream(pStream)
 {
     CONTRACTL
     {
@@ -22,6 +22,17 @@ IpcStreamWriter::IpcStreamWriter(IpcStream *pStream) : _pStream(pStream)
         PRECONDITION(_pStream != nullptr);
     }
     CONTRACTL_END;
+
+    if (_pStream == nullptr)
+        return;
+
+    uint32_t nBytesWritten = 0;
+    bool fSuccess = _pStream->Write(&id, sizeof(id), nBytesWritten);
+    if (!fSuccess)
+    {
+        delete _pStream;
+        _pStream = nullptr;
+    }
 }
 
 IpcStreamWriter::~IpcStreamWriter()
@@ -51,6 +62,8 @@ bool IpcStreamWriter::Write(const void *lpBuffer, const uint32_t nBytesToWrite,
 
     if (_pStream == nullptr)
         return false;
+    if (lpBuffer == nullptr || nBytesToWrite == 0)
+        return false;
     return _pStream->Write(lpBuffer, nBytesToWrite, nBytesWritten);
 }
 
index d5db786..2c669f0 100644 (file)
@@ -53,12 +53,12 @@ public:
 class IpcStreamWriter final : public StreamWriter
 {
 public:
-    IpcStreamWriter(IpcStream *pStream);
+    IpcStreamWriter(uint64_t id, IpcStream *pStream);
     ~IpcStreamWriter();
     bool Write(const void *lpBuffer, const uint32_t nBytesToWrite, uint32_t &nBytesWritten) const;
 
 private:
-    IpcStream *const _pStream;
+    IpcStream *_pStream;
 };
 
 //!