Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prototype
  • Loading branch information
cshung committed Jul 27, 2020
commit c265294f4aaff88329665b3823e48b600216ad9e
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,15 @@ public EventPipeSession StartEventPipeSession(EventPipeProvider provider, bool r
/// <param name="dumpType">Type of the dump to be generated</param>
/// <param name="dumpPath">Full path to the dump to be generated. By default it is /tmp/coredump.{pid}</param>
/// <param name="logDumpGeneration">When set to true, display the dump generation debug log to the console.</param>
public void WriteDump(DumpType dumpType, string dumpPath, bool logDumpGeneration=false)
/// <param name="condition">The condition</param>
/// <param name="identity">The identity for cancellation</param>
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)
{
Expand Down Expand Up @@ -145,15 +147,16 @@ public static IEnumerable<int> 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))
{
writer.WriteString(dumpName);
writer.Write((uint)dumpType);
writer.Write((uint)(diagnostics ? 1 : 0));

writer.WriteString(condition);
writer.WriteString(identity);
writer.Flush();
return stream.ToArray();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
41 changes: 22 additions & 19 deletions src/Tools/dotnet-dump/Dumper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -83,34 +84,36 @@ 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
Process process = Process.GetProcessById(processId);

Windows.CollectDump(process, output, type);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with this change is that now dotnet-dump collect on Windows won't work with older runtimes (<= 2.2) and it did before. May be it isn't that important because dotnet-dump collect on xplat only works runtimes > 2.2 and your change is needed to provide the condition on Windows.

dotnet-dump could catch that the client.WriteDump fails on the unsupported Windows runtimes, but the exception is inconsistent/difficult than xplat. I think it is something like TimeoutException on Windows and PlatformNotSupportedException on xplat.

/cc: @josalem on the client assembly exception difference.

}
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 ||
Expand Down
12 changes: 10 additions & 2 deletions src/Tools/dotnet-dump/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ private static Command CollectCommand() =>
new Command( name: "collect", description: "Capture dumps from a process")
{
// Handler
CommandHandler.Create<IConsole, int, string, bool, Dumper.DumpTypeOption, string>(new Dumper().Collect),
CommandHandler.Create<IConsole, int, string, bool, Dumper.DumpTypeOption, string, string>(new Dumper().Collect),
// Options
ProcessIdOption(), OutputOption(), DiagnosticLoggingOption(), TypeOption(), ProcessNameOption()
ProcessIdOption(), OutputOption(), DiagnosticLoggingOption(), TypeOption(), ProcessNameOption(), ConditionOption()
};

private static Option ProcessIdOption() =>
Expand All @@ -51,6 +51,14 @@ private static Option ProcessNameOption() =>
Argument = new Argument<string>(name: "name")
};

private static Option ConditionOption() =>
new Option(
aliases: new[] { "-c", "--condition" },
description: "The condition (TODO - documentation).")
{
Argument = new Argument<string>(name: "condition")
};

private static Option OutputOption() =>
new Option(
aliases: new[] { "-o", "--output" },
Expand Down
14 changes: 14 additions & 0 deletions src/Tools/dotnet-dump/build.cmd
Original file line number Diff line number Diff line change
@@ -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
)
)
11 changes: 11 additions & 0 deletions src/Tools/dotnet-dump/run.cmd
Original file line number Diff line number Diff line change
@@ -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%
2 changes: 2 additions & 0 deletions src/Tools/dotnet-gcdump/CommandLine/CollectCommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ internal static class CollectCommandHandler
/// <returns></returns>
private static async Task<int> 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)
Expand Down
14 changes: 14 additions & 0 deletions src/Tools/dotnet-gcdump/build.cmd
Original file line number Diff line number Diff line change
@@ -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
)
)
11 changes: 11 additions & 0 deletions src/Tools/dotnet-gcdump/run.cmd
Original file line number Diff line number Diff line change
@@ -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%