Skip to content

Add enable crash report flag to WriteDump client API #2715

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 1, 2021
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -127,20 +127,61 @@ public void WriteDump(DumpType dumpType, string dumpPath, bool logDumpGeneration
ValidateResponseMessage(response, nameof(WriteDump));
}

/// <summary>
/// Trigger a core dump generation.
/// </summary>
/// <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="flags">logging and crash report flags. On runtimes less than 6.0, only LoggingEnabled is supported.</param>
public void WriteDump(DumpType dumpType, string dumpPath, WriteDumpFlags flags)
{
IpcMessage request = CreateWriteDumpMessage2(dumpType, dumpPath, flags);
IpcMessage response = IpcClient.SendMessage(_endpoint, request);
if (!ValidateResponseMessage(response, nameof(WriteDump), ValidateResponseOptions.UnknownCommandReturnsFalse))
{
if ((flags & ~WriteDumpFlags.LoggingEnabled) != 0)
{
throw new ArgumentException($"Only {nameof(WriteDumpFlags.LoggingEnabled)} flag is supported by this runtime version", nameof(flags));
}
WriteDump(dumpType, dumpPath, logDumpGeneration: (flags & WriteDumpFlags.LoggingEnabled) != 0);
}
}

/// <summary>
/// Trigger a core dump generation.
/// </summary>
/// <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>
/// <param name="token">The token to monitor for cancellation requests.</param>
internal async Task WriteDumpAsync(DumpType dumpType, string dumpPath, bool logDumpGeneration, CancellationToken token)
public async Task WriteDumpAsync(DumpType dumpType, string dumpPath, bool logDumpGeneration, CancellationToken token)
{
IpcMessage request = CreateWriteDumpMessage(dumpType, dumpPath, logDumpGeneration);
IpcMessage response = await IpcClient.SendMessageAsync(_endpoint, request, token).ConfigureAwait(false);
ValidateResponseMessage(response, nameof(WriteDumpAsync));
}

/// <summary>
/// Trigger a core dump generation.
/// </summary>
/// <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="flags">logging and crash report flags. On runtimes less than 6.0, only LoggingEnabled is supported.</param>
/// <param name="token">The token to monitor for cancellation requests.</param>
public async Task WriteDumpAsync(DumpType dumpType, string dumpPath, WriteDumpFlags flags, CancellationToken token)
{
IpcMessage request = CreateWriteDumpMessage2(dumpType, dumpPath, flags);
IpcMessage response = await IpcClient.SendMessageAsync(_endpoint, request, token).ConfigureAwait(false);
if (!ValidateResponseMessage(response, nameof(WriteDumpAsync), ValidateResponseOptions.UnknownCommandReturnsFalse))
{
if ((flags & ~WriteDumpFlags.LoggingEnabled) != 0)
{
throw new ArgumentException($"Only {nameof(WriteDumpFlags.LoggingEnabled)} flag is supported by this runtime version", nameof(flags));
}
await WriteDumpAsync(dumpType, dumpPath, logDumpGeneration: (flags & WriteDumpFlags.LoggingEnabled) != 0, token);
}
}

/// <summary>
/// Attach a profiler.
/// </summary>
Expand Down Expand Up @@ -471,6 +512,15 @@ private static IpcMessage CreateWriteDumpMessage(DumpType dumpType, string dumpP
return new IpcMessage(DiagnosticsServerCommandSet.Dump, (byte)DumpCommandId.GenerateCoreDump, payload);
}

private static IpcMessage CreateWriteDumpMessage2(DumpType dumpType, string dumpPath, WriteDumpFlags flags)
{
if (string.IsNullOrEmpty(dumpPath))
throw new ArgumentNullException($"{nameof(dumpPath)} required");

byte[] payload = SerializePayload(dumpPath, (uint)dumpType, (uint)flags);
return new IpcMessage(DiagnosticsServerCommandSet.Dump, (byte)DumpCommandId.GenerateCoreDump2, payload);
}

private static ProcessInfo GetProcessInfoFromResponse(IpcResponse response, string operationName)
{
ValidateResponseMessage(response.Message, operationName);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// 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.

namespace Microsoft.Diagnostics.NETCore.Client
{
public enum WriteDumpFlags
{
None = 0x00,
LoggingEnabled = 0x01,
VerboseLoggingEnabled = 0x02,
CrashReportEnabled = 0x04
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ internal enum EventPipeCommandId : byte
internal enum DumpCommandId : byte
{
GenerateCoreDump = 0x01,
GenerateCoreDump2 = 0x02,
}

internal enum ProfilerCommandId : byte
Expand Down
19 changes: 17 additions & 2 deletions src/Tools/dotnet-dump/Dumper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ 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, bool crashreport, DumpTypeOption type, string name)
{
Console.WriteLine(name);
if (name != null)
Expand Down Expand Up @@ -86,6 +86,12 @@ public int Collect(IConsole console, int processId, string output, bool diag, Du

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
if (crashreport)
Copy link
Member

Choose a reason for hiding this comment

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

How is this not supported on Windows? I thought crash reports were possible on Windows. I seen many programs use such a thing before there too.

Copy link
Author

Choose a reason for hiding this comment

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

The crash report referenced here is a special json file that the Linux and MacOS tool createdump tool generates. The Windows "createdump" just calls the OS's MiniDumpWriteDump to generate dump and doesn't have a way to generate this json file. On Linux and MacOS createdump explicitly gathers the runtime process's state and writes both the core dump and the crash report json from that data.

{
Console.WriteLine("Crash reports not supported on Windows.");
return 0;
}

// Get the process
Process process = Process.GetProcessById(processId);

Expand All @@ -112,8 +118,17 @@ public int Collect(IConsole console, int processId, string output, bool diag, Du
break;
}

WriteDumpFlags flags = WriteDumpFlags.None;
if (diag)
{
flags |= WriteDumpFlags.LoggingEnabled;
}
if (crashreport)
{
flags |= WriteDumpFlags.CrashReportEnabled;
}
// Send the command to the runtime to initiate the core dump
client.WriteDump(dumpType, output, diag);
client.WriteDump(dumpType, output, flags);
}
}
catch (Exception ex) when
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 @@ -32,9 +32,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, bool, Dumper.DumpTypeOption, string>(new Dumper().Collect),
// Options
ProcessIdOption(), OutputOption(), DiagnosticLoggingOption(), TypeOption(), ProcessNameOption()
ProcessIdOption(), OutputOption(), DiagnosticLoggingOption(), CrashReportOption(), TypeOption(), ProcessNameOption()
};

private static Option ProcessIdOption() =>
Expand Down Expand Up @@ -70,6 +70,14 @@ private static Option DiagnosticLoggingOption() =>
Argument = new Argument<bool>(name: "diag")
};

private static Option CrashReportOption() =>
new Option(
alias: "--crashreport",
Copy link
Member

Choose a reason for hiding this comment

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

Is there an issue filed or PR open to add the docs for this new feature to docs.microsoft.com?

Copy link
Author

Choose a reason for hiding this comment

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

Doc issue: #2717

Copy link
Member

Choose a reason for hiding this comment

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

That issue covers the APIs, but doesn't mention dotnet-dump the tool and the new argument being added here. Can you either expand the scope of the issue or add a new one?

Copy link
Author

Choose a reason for hiding this comment

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

I added a comment about the new option to the doc issue.

description: "Enable crash report generation.")
{
Argument = new Argument<bool>(name: "crashreport")
};

private static Option TypeOption() =>
new Option(
alias: "--type",
Expand Down