From: Mike McLaughlin Date: Mon, 1 Nov 2021 16:12:47 +0000 (-0700) Subject: Add enable crash report flag to WriteDump client API (#2715) X-Git-Tag: submit/tizen/20220302.040122~18^2^2~30 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dee96ea0c2e6c3498c9500572c987b09aec42e48;p=platform%2Fcore%2Fdotnet%2Fdiagnostics.git Add enable crash report flag to WriteDump client API (#2715) Add enable crash report flag to WriteDump client API Uses new write dump command supported by 6.0 runtime to pass a set of flags instead of just the logging enabled bool. Issue: https://github.com/dotnet/diagnostics/issues/2698 Code review feedback. Throw exception on unsupported flags --- diff --git a/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/DiagnosticsClient.cs b/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/DiagnosticsClient.cs index d77497edf..30f912f4f 100644 --- a/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/DiagnosticsClient.cs +++ b/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/DiagnosticsClient.cs @@ -127,6 +127,26 @@ namespace Microsoft.Diagnostics.NETCore.Client ValidateResponseMessage(response, nameof(WriteDump)); } + /// + /// Trigger a core dump generation. + /// + /// Type of the dump to be generated + /// Full path to the dump to be generated. By default it is /tmp/coredump.{pid} + /// logging and crash report flags. On runtimes less than 6.0, only LoggingEnabled is supported. + 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); + } + } + /// /// Trigger a core dump generation. /// @@ -134,13 +154,34 @@ namespace Microsoft.Diagnostics.NETCore.Client /// 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. /// The token to monitor for cancellation requests. - 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)); } + /// + /// Trigger a core dump generation. + /// + /// Type of the dump to be generated + /// Full path to the dump to be generated. By default it is /tmp/coredump.{pid} + /// logging and crash report flags. On runtimes less than 6.0, only LoggingEnabled is supported. + /// The token to monitor for cancellation requests. + 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); + } + } + /// /// Attach a profiler. /// @@ -471,6 +512,15 @@ namespace Microsoft.Diagnostics.NETCore.Client 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); diff --git a/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/WriteDumpFlags.cs b/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/WriteDumpFlags.cs new file mode 100644 index 000000000..b1f93cd59 --- /dev/null +++ b/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/WriteDumpFlags.cs @@ -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 + } +} \ No newline at end of file diff --git a/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcCommands.cs b/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcCommands.cs index d76f0df0b..b1f4e80ef 100644 --- a/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcCommands.cs +++ b/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcCommands.cs @@ -35,6 +35,7 @@ namespace Microsoft.Diagnostics.NETCore.Client 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 8d9140a96..ce8ec9d5c 100644 --- a/src/Tools/dotnet-dump/Dumper.cs +++ b/src/Tools/dotnet-dump/Dumper.cs @@ -34,7 +34,7 @@ namespace Microsoft.Diagnostics.Tools.Dump { } - 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) @@ -86,6 +86,12 @@ namespace Microsoft.Diagnostics.Tools.Dump if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { + if (crashreport) + { + Console.WriteLine("Crash reports not supported on Windows."); + return 0; + } + // Get the process Process process = Process.GetProcessById(processId); @@ -112,8 +118,17 @@ namespace Microsoft.Diagnostics.Tools.Dump 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 diff --git a/src/Tools/dotnet-dump/Program.cs b/src/Tools/dotnet-dump/Program.cs index f3b2bafbc..aed69c55b 100644 --- a/src/Tools/dotnet-dump/Program.cs +++ b/src/Tools/dotnet-dump/Program.cs @@ -32,9 +32,9 @@ namespace Microsoft.Diagnostics.Tools.Dump 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(), CrashReportOption(), TypeOption(), ProcessNameOption() }; private static Option ProcessIdOption() => @@ -70,6 +70,14 @@ on Linux where YYYYMMDD is Year/Month/Day and HHMMSS is Hour/Minute/Second. Othe Argument = new Argument(name: "diag") }; + private static Option CrashReportOption() => + new Option( + alias: "--crashreport", + description: "Enable crash report generation.") + { + Argument = new Argument(name: "crashreport") + }; + private static Option TypeOption() => new Option( alias: "--type",