forked from dotnet/runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathautotrace.cpp
129 lines (112 loc) · 3.98 KB
/
autotrace.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
/**
*
* AutoTrace: This infrastructure is used to run automated testing of Diagnostic Server based tracing via
* EventPipe. The feature itself is enabled via the feature flag FEATURE_AUTO_TRACE.
*
* Two environment variables dictate behavior:
* - DOTNET_AutoTrace_N_Tracers: a number in [0,64] where 0 will disable the feature
* - DOTNET_AutoTrace_Command: The path to an executable to be invoked. Typically this will be a "run.sh|cmd".
* > (NB: you should `cd` into the directory you intend to execute `DOTNET_AutoTrace_Command` from as the first line of the script.)
*
* Once turned on, AutoTrace will run the specified command `DOTNET_AutoTrace_N_Tracers` times. There is an event that will pause execution
* of the runtime until all the tracers have attached. Once all the tracers are attached, execution will continue normally.
*
* This logic is easily modified to accommodate testing other mechanisms related to the Diagnostic Server.
*
*/
#include "common.h" // Required for pre-compiled header
#ifdef FEATURE_AUTO_TRACE
#ifdef TARGET_UNIX
#include "pal.h"
#endif // TARGET_UNIX
HANDLE auto_trace_event;
static size_t g_n_tracers = 1;
static WCHAR* command = nullptr;
void auto_trace_init()
{
if (CLRConfig::IsConfigEnabled(CLRConfig::INTERNAL_AutoTrace_N_Tracers))
{
g_n_tracers = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_AutoTrace_N_Tracers);
}
// Get the command to run auto-trace. Note that the `-p <pid>` option
// will be automatically added for you
LPWSTR commandTextValue = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_AutoTrace_Command);
if (commandTextValue != NULL)
{
// Create a command line with the format: "%s -p %d"
const WCHAR flagFormat[] = W(" -p ");
DWORD currentProcessId = GetCurrentProcessId();
size_t bufferLen = 8192;
size_t written = 0;
command = new WCHAR[bufferLen];
// Copy in the command - %s
wcscpy_s(command, bufferLen, commandTextValue);
written += u16_strlen(commandTextValue);
// Append " -p "
wcscat_s(command, bufferLen - written, flagFormat);
written += ARRAY_SIZE(flagFormat) - 1;
// Append the process ID
FormatInteger(command + written, bufferLen - written, "%d", currentProcessId);
}
else
{
// we don't have anything to run, just set
// n tracers to 0...
g_n_tracers = 0;
}
auto_trace_event = CreateEventW(
/* lpEventAttributes = */ NULL,
/* bManualReset = */ FALSE,
/* bInitialState = */ FALSE,
/* lpName = */ nullptr
);
}
void auto_trace_launch_internal()
{
DWORD currentProcessId = GetCurrentProcessId();
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(STARTUPINFO);
#ifndef TARGET_UNIX
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
#endif
PROCESS_INFORMATION result;
BOOL code = CreateProcessW(
/* lpApplicationName = */ nullptr,
/* lpCommandLine = */ command,
/* lpCommandLine = */ nullptr,
/* lpThreadAttributes = */ nullptr,
/* bInheritHandles = */ false,
/* dwCreationFlags = */ CREATE_NEW_CONSOLE,
/* lpEnvironment = */ nullptr,
/* lpCurrentDirectory = */ nullptr,
/* lpStartupInfo = */ &si,
/* lpProcessInformation = */ &result
);
}
void auto_trace_launch()
{
for (size_t i = 0; i < g_n_tracers; ++i)
{
auto_trace_launch_internal();
}
delete[] command;
}
void auto_trace_wait()
{
if (g_n_tracers > 0)
WaitForSingleObject(auto_trace_event, INFINITE);
}
void auto_trace_signal()
{
#ifdef SetEvent
#undef SetEvent
#endif
static size_t nCalls = 0;
if (++nCalls == g_n_tracers)
SetEvent(auto_trace_event);
}
#endif // FEATURE_AUTO_TRACE