summaryrefslogtreecommitdiff
path: root/src/vm
diff options
context:
space:
mode:
authorSung Yoon Whang <suwhang@microsoft.com>2019-07-02 00:08:30 -0700
committerGitHub <noreply@github.com>2019-07-02 00:08:30 -0700
commiteb13fb092778db9fa8a0dea755393494959b71a6 (patch)
treed2a2870b7a992432ef0b7b53283fd6cfaf6dff1f /src/vm
parentf9a6e873747dbefeca9016e31378d532ce56f293 (diff)
downloadcoreclr-eb13fb092778db9fa8a0dea755393494959b71a6.tar.gz
coreclr-eb13fb092778db9fa8a0dea755393494959b71a6.tar.bz2
coreclr-eb13fb092778db9fa8a0dea755393494959b71a6.zip
Add RundownRequested switch to EventPipe IPC protocol (#25495)
* Add RundownRequested switch to EventPipe IPC protocol * Fix linux build * make the rundownRequested field a bool * some renaming * Make a new command that has an option for disabling rundown instead of breaking change * code review feedback
Diffstat (limited to 'src/vm')
-rw-r--r--src/vm/eventpipe.cpp35
-rw-r--r--src/vm/eventpipe.h1
-rw-r--r--src/vm/eventpipeinternal.cpp1
-rw-r--r--src/vm/eventpipeprotocolhelper.cpp81
-rw-r--r--src/vm/eventpipeprotocolhelper.h25
-rw-r--r--src/vm/eventpipesession.cpp4
-rw-r--r--src/vm/eventpipesession.h11
7 files changed, 140 insertions, 18 deletions
diff --git a/src/vm/eventpipe.cpp b/src/vm/eventpipe.cpp
index 670c38692d..4ca57a274c 100644
--- a/src/vm/eventpipe.cpp
+++ b/src/vm/eventpipe.cpp
@@ -168,6 +168,7 @@ EventPipeSessionID EventPipe::Enable(
uint32_t numProviders,
EventPipeSessionType sessionType,
EventPipeSerializationFormat format,
+ const bool rundownRequested,
IpcStream *const pStream)
{
CONTRACTL
@@ -202,6 +203,7 @@ EventPipeSessionID EventPipe::Enable(
pStream,
sessionType,
format,
+ rundownRequested,
circularBufferSizeInMB,
pProviders,
numProviders);
@@ -344,26 +346,29 @@ void EventPipe::DisableInternal(EventPipeSessionID id, EventPipeProviderCallback
pSession->Disable(); // Suspend EventPipeBufferManager, and remove providers.
- // Do rundown before fully stopping the session.
- pSession->EnableRundown(); // Set Rundown provider.
-
- EventPipeThread *const pEventPipeThread = EventPipeThread::GetOrCreate();
- if (pEventPipeThread != nullptr)
+ // Do rundown before fully stopping the session unless rundown wasn't requested
+ if (pSession->RundownRequested())
{
- pEventPipeThread->SetAsRundownThread(pSession);
+ pSession->EnableRundown(); // Set Rundown provider.
+
+ EventPipeThread *const pEventPipeThread = EventPipeThread::GetOrCreate();
+ if (pEventPipeThread != nullptr)
{
- s_config.Enable(*pSession, pEventPipeProviderCallbackDataQueue);
+ pEventPipeThread->SetAsRundownThread(pSession);
{
- pSession->ExecuteRundown();
+ s_config.Enable(*pSession, pEventPipeProviderCallbackDataQueue);
+ {
+ pSession->ExecuteRundown();
+ }
+ s_config.Disable(*pSession, pEventPipeProviderCallbackDataQueue);
}
- s_config.Disable(*pSession, pEventPipeProviderCallbackDataQueue);
+ pEventPipeThread->SetAsRundownThread(nullptr);
+ }
+ else
+ {
+ _ASSERTE(!"Failed to get or create the EventPipeThread for rundown events.");
+ return;
}
- pEventPipeThread->SetAsRundownThread(nullptr);
- }
- else
- {
- _ASSERTE(!"Failed to get or create the EventPipeThread for rundown events.");
- return;
}
--s_numberOfSessions;
diff --git a/src/vm/eventpipe.h b/src/vm/eventpipe.h
index 9889abcb52..de2e72f4e8 100644
--- a/src/vm/eventpipe.h
+++ b/src/vm/eventpipe.h
@@ -51,6 +51,7 @@ public:
uint32_t numProviders,
EventPipeSessionType sessionType,
EventPipeSerializationFormat format,
+ const bool rundownRequested,
IpcStream *const pStream);
// Disable tracing via the event pipe.
diff --git a/src/vm/eventpipeinternal.cpp b/src/vm/eventpipeinternal.cpp
index 90c51d46ab..e79005dd85 100644
--- a/src/vm/eventpipeinternal.cpp
+++ b/src/vm/eventpipeinternal.cpp
@@ -46,6 +46,7 @@ UINT64 QCALLTYPE EventPipeInternal::Enable(
numProviders,
outputFile != NULL ? EventPipeSessionType::File : EventPipeSessionType::Listener,
format,
+ true,
nullptr);
}
END_QCALL;
diff --git a/src/vm/eventpipeprotocolhelper.cpp b/src/vm/eventpipeprotocolhelper.cpp
index f928f326e6..e60e998469 100644
--- a/src/vm/eventpipeprotocolhelper.cpp
+++ b/src/vm/eventpipeprotocolhelper.cpp
@@ -38,6 +38,44 @@ static bool TryParseSerializationFormat(uint8_t*& bufferCursor, uint32_t& buffer
return CanParse && (0 <= (int)serializationFormat) && ((int)serializationFormat < (int)EventPipeSerializationFormat::Count);
}
+static bool TryParseRundownRequested(uint8_t*& bufferCursor, uint32_t& bufferLen, bool& rundownRequested)
+{
+ return TryParse(bufferCursor, bufferLen, rundownRequested);
+}
+
+const EventPipeCollectTracing2CommandPayload* EventPipeCollectTracing2CommandPayload::TryParse(BYTE* lpBuffer, uint16_t& BufferSize)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(lpBuffer != nullptr);
+ }
+ CONTRACTL_END;
+
+ EventPipeCollectTracing2CommandPayload *payload = new (nothrow) EventPipeCollectTracing2CommandPayload;
+ if (payload == nullptr)
+ {
+ // OOM
+ return nullptr;
+ }
+
+ payload->incomingBuffer = lpBuffer;
+ uint8_t* pBufferCursor = payload->incomingBuffer;
+ uint32_t bufferLen = BufferSize;
+ if (!TryParseCircularBufferSize(pBufferCursor, bufferLen, payload->circularBufferSizeInMB) ||
+ !TryParseSerializationFormat(pBufferCursor, bufferLen, payload->serializationFormat) ||
+ !TryParseRundownRequested(pBufferCursor, bufferLen, payload->rundownRequested) ||
+ !EventPipeProtocolHelper::TryParseProviderConfiguration(pBufferCursor, bufferLen, payload->providerConfigs))
+ {
+ delete payload;
+ return nullptr;
+ }
+
+ return payload;
+}
+
const EventPipeCollectTracingCommandPayload* EventPipeCollectTracingCommandPayload::TryParse(BYTE* lpBuffer, uint16_t& BufferSize)
{
CONTRACTL
@@ -86,7 +124,9 @@ void EventPipeProtocolHelper::HandleIpcMessage(DiagnosticsIpc::IpcMessage& messa
case EventPipeCommandId::CollectTracing:
EventPipeProtocolHelper::CollectTracing(message, pStream);
break;
-
+ case EventPipeCommandId::CollectTracing2:
+ EventPipeProtocolHelper::CollectTracing2(message, pStream);
+ break;
case EventPipeCommandId::StopTracing:
EventPipeProtocolHelper::StopTracing(message, pStream);
break;
@@ -200,6 +240,45 @@ void EventPipeProtocolHelper::CollectTracing(DiagnosticsIpc::IpcMessage& message
static_cast<uint32_t>(payload->providerConfigs.Size()), // numConfigs
EventPipeSessionType::IpcStream, // EventPipeSessionType
payload->serializationFormat, // EventPipeSerializationFormat
+ true, // rundownRequested
+ pStream); // IpcStream
+
+ if (sessionId == 0)
+ {
+ DiagnosticsIpc::IpcMessage::SendErrorMessage(pStream, E_FAIL);
+ delete payload;
+ delete pStream;
+ }
+}
+
+void EventPipeProtocolHelper::CollectTracing2(DiagnosticsIpc::IpcMessage& message, IpcStream *pStream)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(pStream != nullptr);
+ }
+ CONTRACTL_END;
+
+ const EventPipeCollectTracing2CommandPayload* payload = message.TryParsePayload<EventPipeCollectTracing2CommandPayload>();
+ if (payload == nullptr)
+ {
+ DiagnosticsIpc::IpcMessage::SendErrorMessage(pStream, CORDIAGIPC_E_BAD_ENCODING);
+ delete payload;
+ delete pStream;
+ return;
+ }
+
+ auto sessionId = EventPipe::Enable(
+ nullptr, // strOutputPath (ignored in this scenario)
+ payload->circularBufferSizeInMB, // circularBufferSizeInMB
+ payload->providerConfigs.Ptr(), // pConfigs
+ static_cast<uint32_t>(payload->providerConfigs.Size()), // numConfigs
+ EventPipeSessionType::IpcStream, // EventPipeSessionType
+ payload->serializationFormat, // EventPipeSerializationFormat
+ payload->rundownRequested, // rundownRequested
pStream); // IpcStream
if (sessionId == 0)
diff --git a/src/vm/eventpipeprotocolhelper.h b/src/vm/eventpipeprotocolhelper.h
index 5ae7abdc67..98d058b631 100644
--- a/src/vm/eventpipeprotocolhelper.h
+++ b/src/vm/eventpipeprotocolhelper.h
@@ -20,9 +20,32 @@ enum class EventPipeCommandId : uint8_t
{
StopTracing = 0x01,
CollectTracing = 0x02,
+ CollectTracing2 = 0x03,
// future
};
+
+// Command = 0x0203
+struct EventPipeCollectTracing2CommandPayload
+{
+ NewArrayHolder<BYTE> incomingBuffer;
+
+ // 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, uint format, array<provider_config> providers
+ // uint = 4 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
+ uint32_t circularBufferSizeInMB;
+ EventPipeSerializationFormat serializationFormat;
+ bool rundownRequested;
+ CQuickArray<EventPipeProviderConfiguration> providerConfigs;
+ static const EventPipeCollectTracing2CommandPayload* TryParse(BYTE* lpBuffer, uint16_t& BufferSize);
+};
+
+
// Command = 0x0202
struct EventPipeCollectTracingCommandPayload
{
@@ -55,10 +78,10 @@ public:
static void HandleIpcMessage(DiagnosticsIpc::IpcMessage& message, IpcStream *pStream);
static void StopTracing(DiagnosticsIpc::IpcMessage& message, IpcStream *pStream);
static void CollectTracing(DiagnosticsIpc::IpcMessage& message, IpcStream *pStream); // `dotnet-trace collect`
+ static void CollectTracing2(DiagnosticsIpc::IpcMessage& message, IpcStream *pStream);
static bool TryParseProviderConfiguration(uint8_t *&bufferCursor, uint32_t &bufferLen, CQuickArray<EventPipeProviderConfiguration> &result);
private:
- const static uint32_t DefaultCircularBufferMB = 1024; // 1 GB
const static uint32_t IpcStreamReadBufferSize = 8192;
};
diff --git a/src/vm/eventpipesession.cpp b/src/vm/eventpipesession.cpp
index 8123c7e214..aa18df2dec 100644
--- a/src/vm/eventpipesession.cpp
+++ b/src/vm/eventpipesession.cpp
@@ -18,6 +18,7 @@ EventPipeSession::EventPipeSession(
IpcStream *const pStream,
EventPipeSessionType sessionType,
EventPipeSerializationFormat format,
+ bool rundownSwitch,
uint32_t circularBufferSizeInMB,
const EventPipeProviderConfiguration *pProviders,
uint32_t numProviders,
@@ -25,7 +26,8 @@ EventPipeSession::EventPipeSession(
m_pProviderList(new EventPipeSessionProviderList(pProviders, numProviders)),
m_rundownEnabled(rundownEnabled),
m_SessionType(sessionType),
- m_format(format)
+ m_format(format),
+ m_rundownRequested(rundownSwitch)
{
CONTRACTL
{
diff --git a/src/vm/eventpipesession.h b/src/vm/eventpipesession.h
index 277729354d..5e2f4b32c5 100644
--- a/src/vm/eventpipesession.h
+++ b/src/vm/eventpipesession.h
@@ -66,6 +66,9 @@ private:
// irrelevant.
EventPipeSerializationFormat m_format;
+ // For determininig if a particular session needs rundown events
+ const bool m_rundownRequested;
+
// Start date and time in UTC.
FILETIME m_sessionStartTime;
@@ -99,6 +102,7 @@ public:
IpcStream *const pStream,
EventPipeSessionType sessionType,
EventPipeSerializationFormat format,
+ bool rundownRequested,
uint32_t circularBufferSizeInMB,
const EventPipeProviderConfiguration *pProviders,
uint32_t numProviders,
@@ -131,6 +135,13 @@ public:
return m_format;
}
+ // Get whether rundown was requested by the client.
+ bool RundownRequested() const
+ {
+ LIMITED_METHOD_CONTRACT;
+ return m_rundownRequested;
+ }
+
// Determine if rundown is enabled.
bool RundownEnabled() const
{