1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
6 #include "diagnosticserver.h"
7 #include "eventpipeprotocolhelper.h"
8 #include "diagnosticprotocolhelper.h"
14 #ifdef FEATURE_PERFTRACING
16 IpcStream::DiagnosticsIpc *DiagnosticServer::s_pIpc = nullptr;
18 static DWORD WINAPI DiagnosticsServerThread(LPVOID lpThreadParameter)
25 PRECONDITION(lpThreadParameter != nullptr);
29 auto pIpc = reinterpret_cast<IpcStream::DiagnosticsIpc *>(lpThreadParameter);
32 STRESS_LOG0(LF_DIAGNOSTICS_PORT, LL_ERROR, "Diagnostics IPC listener was undefined\n");
36 ErrorCallback LoggingCallback = [](const char *szMessage, uint32_t code) {
37 STRESS_LOG2(LF_DIAGNOSTICS_PORT, LL_WARNING, "warning (%d): %s.\n", code, szMessage);
44 // FIXME: Ideally this would be something like a std::shared_ptr
45 IpcStream *pStream = pIpc->Accept(LoggingCallback);
46 if (pStream == nullptr)
49 // TODO: Read operation should happen in a loop.
50 uint32_t nNumberOfBytesRead = 0;
52 bool fSuccess = pStream->Read(&header, sizeof(header), nNumberOfBytesRead);
53 if (!fSuccess || nNumberOfBytesRead != sizeof(header))
59 switch (header.RequestType)
61 case DiagnosticMessageType::StopEventPipeTracing:
62 EventPipeProtocolHelper::StopTracing(pStream);
65 case DiagnosticMessageType::CollectEventPipeTracing:
66 EventPipeProtocolHelper::CollectTracing(pStream);
70 case DiagnosticMessageType::GenerateCoreDump:
71 DiagnosticProtocolHelper::GenerateCoreDump(pStream);
76 STRESS_LOG1(LF_DIAGNOSTICS_PORT, LL_WARNING, "Received unknown request type (%d)\n", header.RequestType);
84 STRESS_LOG0(LF_DIAGNOSTICS_PORT, LL_ERROR, "Exception caught in diagnostic thread. Leaving thread now.\n");
85 _ASSERTE(!"Hit an error in the diagnostic server thread\n.");
87 EX_END_CATCH(SwallowAllExceptions);
92 bool DiagnosticServer::Initialize()
102 bool fSuccess = false;
106 auto ErrorCallback = [](const char *szMessage, uint32_t code) {
108 LF_DIAGNOSTICS_PORT, // facility
110 "Failed to create diagnostic IPC: error (%d): %s.\n", // msg
115 // TODO: Should we handle/assert that (s_pIpc == nullptr)?
116 s_pIpc = IpcStream::DiagnosticsIpc::Create(
117 "dotnetcore-diagnostic", ErrorCallback);
119 if (s_pIpc != nullptr)
121 DWORD dwThreadId = 0;
122 HANDLE hThread = ::CreateThread( // TODO: Is it correct to have this "lower" level call here?
123 nullptr, // no security attribute
124 0, // default stack size
125 DiagnosticsServerThread, // thread proc
126 (LPVOID)s_pIpc, // thread parameter
128 &dwThreadId); // returns thread ID
130 if (hThread == nullptr)
132 // Failed to create IPC thread.
134 LF_DIAGNOSTICS_PORT, // facility
136 "Failed to create diagnostic server thread (%d).\n", // msg
137 ::GetLastError()); // data1
141 // FIXME: Maybe hold on to the thread to abort/cleanup at exit?
142 ::CloseHandle(hThread);
144 // TODO: Add error handling?
151 // TODO: Should we log anything here?
153 EX_END_CATCH(SwallowAllExceptions);
158 bool DiagnosticServer::Shutdown()
168 bool fSuccess = false;
172 if (s_pIpc != nullptr)
174 auto ErrorCallback = [](const char *szMessage, uint32_t code) {
176 LF_DIAGNOSTICS_PORT, // facility
178 "Failed to unlink diagnostic IPC: error (%d): %s.\n", // msg
182 s_pIpc->Unlink(ErrorCallback);
189 // TODO: Should we log anything here?
191 EX_END_CATCH(SwallowAllExceptions);
196 #endif // FEATURE_PERFTRACING