summaryrefslogtreecommitdiff
path: root/src/vm/diagnosticserver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/diagnosticserver.cpp')
-rw-r--r--src/vm/diagnosticserver.cpp171
1 files changed, 171 insertions, 0 deletions
diff --git a/src/vm/diagnosticserver.cpp b/src/vm/diagnosticserver.cpp
new file mode 100644
index 0000000000..c0e11d100f
--- /dev/null
+++ b/src/vm/diagnosticserver.cpp
@@ -0,0 +1,171 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include "common.h"
+#include "diagnosticserver.h"
+#include "diagnosticsipc.h"
+#include "eventpipeprotocolhelper.h"
+
+#ifdef FEATURE_PAL
+#include "pal.h"
+#endif // FEATURE_PAL
+
+#ifdef FEATURE_PERFTRACING
+
+static DWORD WINAPI DiagnosticsServerThread(LPVOID lpThreadParameter)
+{
+ CONTRACTL
+ {
+ // TODO: Maybe this should not throw.
+ THROWS;
+ GC_TRIGGERS;
+ MODE_ANY;
+ PRECONDITION(lpThreadParameter != nullptr);
+ }
+ CONTRACTL_END;
+
+ auto pIpc = reinterpret_cast<IpcStream::DiagnosticsIpc *>(lpThreadParameter);
+ if (pIpc == nullptr)
+ {
+ STRESS_LOG0(LF_STARTUP, LL_ERROR,"Diagnostics IPC listener was undefined\n");
+ return 1;
+ }
+
+#ifdef _DEBUG
+ ErrorCallback LoggingCallback = [](const char *szMessage, uint32_t code) {
+ LOG((LF_REMOTING, LL_WARNING, "warning (%d): %s.\n", code, szMessage));
+ };
+#else
+ ErrorCallback LoggingCallback = nullptr;
+#endif
+
+ while (true)
+ {
+ // FIXME: Ideally this would be something like a std::shared_ptr
+ IpcStream *pStream = pIpc->Accept(LoggingCallback);
+ if (pStream == nullptr)
+ continue;
+
+ // TODO: Read operation should happen in a loop.
+ uint32_t nNumberOfBytesRead = 0;
+ MessageHeader header;
+ bool fSuccess = pStream->Read(&header, sizeof(header), nNumberOfBytesRead);
+ if (!fSuccess || nNumberOfBytesRead != sizeof(header))
+ {
+ delete pStream;
+ continue;
+ }
+
+ // TODO: Dispatch thread worker.
+ switch (header.RequestType)
+ {
+ case DiagnosticMessageType::EnableEventPipe:
+ EventPipeProtocolHelper::EnableFileTracingEventHandler(pStream);
+ break;
+
+ case DiagnosticMessageType::DisableEventPipe:
+ EventPipeProtocolHelper::DisableTracingEventHandler(pStream);
+ break;
+
+ default:
+ LOG((LF_REMOTING, LL_WARNING, "Received unknow request type (%d)\n", header.RequestType));
+ break;
+ }
+ }
+
+ return 0;
+}
+
+bool DiagnosticServer::Initialize()
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ bool fSuccess = false;
+
+ EX_TRY
+ {
+ auto ErrorCallback = [](const char *szMessage, uint32_t code) {
+ STRESS_LOG2(
+ LF_STARTUP, // facility
+ LL_ERROR, // level
+ "Failed to create diagnostic IPC: error (%d): %s.\n", // msg
+ code, // data1
+ szMessage); // data2
+ };
+ IpcStream::DiagnosticsIpc *pIpc = IpcStream::DiagnosticsIpc::Create(
+ "dotnetcore-diagnostic", ErrorCallback);
+
+ if (pIpc != nullptr)
+ {
+ DWORD dwThreadId = 0;
+ HANDLE hThread = ::CreateThread( // TODO: Is it correct to have this "lower" level call here?
+ nullptr, // no security attribute
+ 0, // default stack size
+ DiagnosticsServerThread, // thread proc
+ (LPVOID)pIpc, // thread parameter
+ 0, // not suspended
+ &dwThreadId); // returns thread ID
+
+ if (hThread == nullptr)
+ {
+ // Failed to create IPC thread.
+ STRESS_LOG1(
+ LF_STARTUP, // facility
+ LL_ERROR, // level
+ "Failed to create diagnostic server thread (%d).\n", // msg
+ ::GetLastError()); // data1
+ }
+ else
+ {
+ // FIXME: Maybe hold on to the thread to abort/cleanup at exit?
+ ::CloseHandle(hThread);
+
+ // TODO: Add error handling?
+ fSuccess = true;
+ }
+ }
+ }
+ EX_CATCH
+ {
+ // TODO: Should we log anything here?
+ }
+ EX_END_CATCH(SwallowAllExceptions);
+
+ return fSuccess;
+}
+
+bool DiagnosticServer::Shutdown()
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ bool fSuccess = false;
+
+ EX_TRY
+ {
+ // FIXME: Stop IPC server thread?
+ fSuccess = true;
+ }
+ EX_CATCH
+ {
+ fSuccess = false;
+ // TODO: Should we log anything here?
+ }
+ EX_END_CATCH(SwallowAllExceptions);
+
+ return fSuccess;
+}
+
+#endif // FEATURE_PERFTRACING