diff --git a/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/DiagnosticsClient.cs b/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/DiagnosticsClient.cs
index 480f1e8892..d1dfba8a69 100644
--- a/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/DiagnosticsClient.cs
+++ b/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/DiagnosticsClient.cs
@@ -69,13 +69,15 @@ public EventPipeSession StartEventPipeSession(EventPipeProvider provider, bool r
/// Type of the dump to be generated
/// Full path to the dump to be generated. By default it is /tmp/coredump.{pid}
/// When set to true, display the dump generation debug log to the console.
- public void WriteDump(DumpType dumpType, string dumpPath, bool logDumpGeneration=false)
+ /// The condition
+ /// The identity for cancellation
+ public void WriteDump(DumpType dumpType, string dumpPath, bool logDumpGeneration=false, string condition=null, string identity=null)
{
if (string.IsNullOrEmpty(dumpPath))
throw new ArgumentNullException($"{nameof(dumpPath)} required");
- byte[] payload = SerializeCoreDump(dumpPath, dumpType, logDumpGeneration);
- IpcMessage message = new IpcMessage(DiagnosticsServerCommandSet.Dump, (byte)DumpCommandId.GenerateCoreDump, payload);
+ byte[] payload = SerializeCoreDumpV2(dumpPath, dumpType, logDumpGeneration, condition, identity);
+ IpcMessage message = new IpcMessage(DiagnosticsServerCommandSet.Dump, (byte)DumpCommandId.GenerateCoreDump2, payload);
IpcMessage response = IpcClient.SendMessage(_processId, message);
switch ((DiagnosticsServerCommandId)response.Header.CommandId)
{
@@ -145,7 +147,7 @@ public static IEnumerable GetPublishedProcesses()
.Distinct();
}
- private static byte[] SerializeCoreDump(string dumpName, DumpType dumpType, bool diagnostics)
+ private static byte[] SerializeCoreDumpV2(string dumpName, DumpType dumpType, bool diagnostics, string condition, string identity)
{
using (var stream = new MemoryStream())
using (var writer = new BinaryWriter(stream))
@@ -153,7 +155,8 @@ private static byte[] SerializeCoreDump(string dumpName, DumpType dumpType, bool
writer.WriteString(dumpName);
writer.Write((uint)dumpType);
writer.Write((uint)(diagnostics ? 1 : 0));
-
+ writer.WriteString(condition);
+ writer.WriteString(identity);
writer.Flush();
return stream.ToArray();
}
diff --git a/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcCommands.cs b/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcCommands.cs
index 7c870e3c1f..7d7639b98e 100644
--- a/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcCommands.cs
+++ b/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcCommands.cs
@@ -28,11 +28,13 @@ internal enum EventPipeCommandId : byte
StopTracing = 0x01,
CollectTracing = 0x02,
CollectTracing2 = 0x03,
+ // TODO, andrewau, a new command for cancelling conditional dump collection
}
internal enum DumpCommandId : byte
{
GenerateCoreDump = 0x01,
+ GenerateCoreDump2 = 0x02,
}
internal enum ProfilerCommandId : byte
diff --git a/src/Tools/dotnet-dump/Dumper.cs b/src/Tools/dotnet-dump/Dumper.cs
index 4a3ce13757..728e4237b0 100644
--- a/src/Tools/dotnet-dump/Dumper.cs
+++ b/src/Tools/dotnet-dump/Dumper.cs
@@ -33,8 +33,9 @@ public Dumper()
{
}
- public int Collect(IConsole console, int processId, string output, bool diag, DumpTypeOption type, string name)
+ public int Collect(IConsole console, int processId, string output, bool diag, DumpTypeOption type, string name, string condition)
{
+ // TODO, andrewau, handle Control+C for cancellation of conditional request
Console.WriteLine(name);
if (name != null)
{
@@ -83,6 +84,8 @@ public int Collect(IConsole console, int processId, string output, bool diag, Du
}
console.Out.WriteLine($"Writing {dumpTypeMessage} to {output}");
+ // TODO, andrewau, be backward compatible to older runtimes
+ /*
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
// Get the process
@@ -90,27 +93,27 @@ public int Collect(IConsole console, int processId, string output, bool diag, Du
Windows.CollectDump(process, output, type);
}
- else
- {
- var client = new DiagnosticsClient(processId);
+ */
- DumpType dumpType = DumpType.Normal;
- switch (type)
- {
- case DumpTypeOption.Full:
- dumpType = DumpType.Full;
- break;
- case DumpTypeOption.Heap:
- dumpType = DumpType.WithHeap;
- break;
- case DumpTypeOption.Mini:
- dumpType = DumpType.Normal;
- break;
- }
+ var client = new DiagnosticsClient(processId);
- // Send the command to the runtime to initiate the core dump
- client.WriteDump(dumpType, output, diag);
+ DumpType dumpType = DumpType.Normal;
+ switch (type)
+ {
+ case DumpTypeOption.Full:
+ dumpType = DumpType.Full;
+ break;
+ case DumpTypeOption.Heap:
+ dumpType = DumpType.WithHeap;
+ break;
+ case DumpTypeOption.Mini:
+ dumpType = DumpType.Normal;
+ break;
}
+
+ // Send the command to the runtime to initiate the core dump
+ Guid identity = Guid.NewGuid();
+ client.WriteDump(dumpType, output, diag, condition, identity.ToString());
}
catch (Exception ex) when
(ex is FileNotFoundException ||
diff --git a/src/Tools/dotnet-dump/Program.cs b/src/Tools/dotnet-dump/Program.cs
index cbbbe50e2e..158a87c025 100644
--- a/src/Tools/dotnet-dump/Program.cs
+++ b/src/Tools/dotnet-dump/Program.cs
@@ -30,9 +30,9 @@ private static Command CollectCommand() =>
new Command( name: "collect", description: "Capture dumps from a process")
{
// Handler
- CommandHandler.Create(new Dumper().Collect),
+ CommandHandler.Create(new Dumper().Collect),
// Options
- ProcessIdOption(), OutputOption(), DiagnosticLoggingOption(), TypeOption(), ProcessNameOption()
+ ProcessIdOption(), OutputOption(), DiagnosticLoggingOption(), TypeOption(), ProcessNameOption(), ConditionOption()
};
private static Option ProcessIdOption() =>
@@ -51,6 +51,14 @@ private static Option ProcessNameOption() =>
Argument = new Argument(name: "name")
};
+ private static Option ConditionOption() =>
+ new Option(
+ aliases: new[] { "-c", "--condition" },
+ description: "The condition (TODO - documentation).")
+ {
+ Argument = new Argument(name: "condition")
+ };
+
private static Option OutputOption() =>
new Option(
aliases: new[] { "-o", "--output" },
diff --git a/src/Tools/dotnet-dump/build.cmd b/src/Tools/dotnet-dump/build.cmd
new file mode 100644
index 0000000000..1efd38f9af
--- /dev/null
+++ b/src/Tools/dotnet-dump/build.cmd
@@ -0,0 +1,14 @@
+@if not defined _echo echo off
+cls
+
+dotnet.exe restore "%~dp0dotnet-dump.csproj" --packages "%~dp0..\..\..\artifacts\packages" || (
+ echo [ERROR] Failed to restore.
+ exit /b 1
+)
+
+for %%c in (Debug Release) do (
+ dotnet.exe build "%~dp0dotnet-dump.csproj" -c %%c --no-restore || (
+ echo [ERROR] Failed to build %%c.
+ exit /b 1
+ )
+)
diff --git a/src/Tools/dotnet-dump/run.cmd b/src/Tools/dotnet-dump/run.cmd
new file mode 100644
index 0000000000..dffa8cf06e
--- /dev/null
+++ b/src/Tools/dotnet-dump/run.cmd
@@ -0,0 +1,11 @@
+@if not defined _echo echo off
+
+call :run_command dotnet.exe run -c Debug --no-restore --no-build -- %*
+exit /b %ERRORLEVEL%
+
+:run_command
+ echo/%USERNAME%@%COMPUTERNAME% "%CD%"
+ echo/[%DATE% %TIME%] $ %*
+ echo/
+ call %*
+ exit /b %ERRORLEVEL%
diff --git a/src/Tools/dotnet-gcdump/CommandLine/CollectCommandHandler.cs b/src/Tools/dotnet-gcdump/CommandLine/CollectCommandHandler.cs
index f756e4ea21..744e6e4b20 100644
--- a/src/Tools/dotnet-gcdump/CommandLine/CollectCommandHandler.cs
+++ b/src/Tools/dotnet-gcdump/CommandLine/CollectCommandHandler.cs
@@ -28,6 +28,8 @@ internal static class CollectCommandHandler
///
private static async Task Collect(CancellationToken ct, IConsole console, int processId, string output, int timeout, bool verbose, string name)
{
+ // TODO, andrewau, support the condition option
+ // TODO, andrewau, handle Ctrl+C for cancellation for conditional request
if (name != null)
{
if (processId != 0)
diff --git a/src/Tools/dotnet-gcdump/build.cmd b/src/Tools/dotnet-gcdump/build.cmd
new file mode 100644
index 0000000000..e15b9efaa1
--- /dev/null
+++ b/src/Tools/dotnet-gcdump/build.cmd
@@ -0,0 +1,14 @@
+@if not defined _echo echo off
+cls
+
+dotnet.exe restore "%~dp0dotnet-gcdump.csproj" --packages "%~dp0..\..\..\artifacts\packages" || (
+ echo [ERROR] Failed to restore.
+ exit /b 1
+)
+
+for %%c in (Debug Release) do (
+ dotnet.exe build "%~dp0dotnet-gcdump.csproj" -c %%c --no-restore || (
+ echo [ERROR] Failed to build %%c.
+ exit /b 1
+ )
+)
diff --git a/src/Tools/dotnet-gcdump/run.cmd b/src/Tools/dotnet-gcdump/run.cmd
new file mode 100644
index 0000000000..dffa8cf06e
--- /dev/null
+++ b/src/Tools/dotnet-gcdump/run.cmd
@@ -0,0 +1,11 @@
+@if not defined _echo echo off
+
+call :run_command dotnet.exe run -c Debug --no-restore --no-build -- %*
+exit /b %ERRORLEVEL%
+
+:run_command
+ echo/%USERNAME%@%COMPUTERNAME% "%CD%"
+ echo/[%DATE% %TIME%] $ %*
+ echo/
+ call %*
+ exit /b %ERRORLEVEL%