Add architecture option dotnet-sos (#450)
authorMike McLaughlin <mikem@microsoft.com>
Tue, 27 Aug 2019 01:12:24 +0000 (18:12 -0700)
committerGitHub <noreply@github.com>
Tue, 27 Aug 2019 01:12:24 +0000 (18:12 -0700)
Add architecture option dotnet-sos

Issue: https://github.com/dotnet/diagnostics/issues/406

Add --diag option to dotnet-dump collect to help diagnose issues like https://github.com/dotnet/diagnostics/issues/449 and others.

Update FAQ.

documentation/FAQ.md
src/SOS/SOS.InstallHelper/InstallHelper.cs
src/Tools/dotnet-dump/Dumper.cs
src/Tools/dotnet-dump/Program.cs
src/Tools/dotnet-sos/Program.cs

index 36beae00940e8c668fe0ec98c9023f8302b158a0..724964de4230bc5604a753feafb3f780794426a2 100644 (file)
@@ -3,7 +3,10 @@ Frequently Asked Questions
 
 * If SOS or dotnet-dump analyze commands display "UNKNOWN" for types or functions names, your core dump may not have all the managed state. Dumps created with gdb or gcore have this problem. Linux system generated core dumps need the `coredump_filter` for the process to be set to at least 0x3f. See [core](http://man7.org/linux/man-pages/man5/core.5.html) for more information.
 
-* If dump collection (`dotnet dump collect` or `createdump`) doesn't work in a docker container, try adding the SYS\_TRACE capablity with --cap-add=SYS\_PTRACE or --privileged.
+* If dump collection (`dotnet-dump collect` or `createdump`) doesn't work in a docker container, try adding the SYS\_TRACE capablity with --cap-add=SYS\_PTRACE or --privileged.
  
-* If dump analysis (`dotnet dump analyze`) on Microsoft .NET Core SDK Linux docker images fails with an`Unhandled exception: System.DllNotFoundException: Unable to load shared library 'libdl.so' or one of its dependencies` exception. Try installing the "libc6-dev" package.
+* If dump analysis (`dotnet-dump analyze`) on Microsoft .NET Core SDK Linux docker images fails with an`Unhandled exception: System.DllNotFoundException: Unable to load shared library 'libdl.so' or one of its dependencies` exception. Try installing the "libc6-dev" package.
  
+* During dump collection (`dotnet-dump collect`) a failure ending in a message like `Permission denied /tmp/dotnet-diagnostic-19668-22628141-socket error` hints you don't have access to use such a socket. Verify the target process is owned by the user trying to create the dump, or trigger dump creation command with `sudo`
+
+* If dump collection (`dotnet-dump collect`) fails with `Core dump generation FAILED 0x80004005` look for error message output on the target process's console (not the console executing the dotnet-dump collect). This error may be caused by writing the core dump to a protected, inaccessible or non-existent location. To get more information about the core dump generation add the `--diag` option the dotnet-dump collect command and look for the diagnostic logging on the target process's console.
index 731e2742937fbaf4a57022bf1834b02a9f560f76..ec637ac88b6d4afd79f5dd5b8129ee088e67350d 100644 (file)
@@ -45,12 +45,14 @@ namespace SOS
         /// <summary>
         /// Create an instance of the installer.
         /// </summary>
+        /// <param name="writeLine">console output delegate</param>
+        /// <param name="architecture">architecture to install or if null using the current process architecture</param>
         /// <exception cref="SOSInstallerException">environment variable not found</exception>
-        public InstallHelper(Action<string> writeLine)
+        public InstallHelper(Action<string> writeLine, Architecture? architecture = null)
         {
             m_writeLine = writeLine;
-            string home = null;
-            string rid = GetRid();
+            string rid = GetRid(architecture);
+            string home;
 
             if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 
             {
@@ -300,7 +302,8 @@ namespace SOS
         /// <summary>
         /// Returns the RID
         /// </summary>
-        public static string GetRid()
+        /// <param name="architecture">architecture to install or if null using the current process architecture</param>
+        public static string GetRid(Architecture? architecture = null)
         {
             string os = null;
             if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
@@ -330,8 +333,8 @@ namespace SOS
             {
                 throw new SOSInstallerException($"Unsupported operating system {RuntimeInformation.OSDescription}");
             }
-            string architecture = RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant();
-            return $"{os}-{architecture}";
+            string architectureString = (architecture.HasValue ? architecture : RuntimeInformation.ProcessArchitecture).ToString().ToLowerInvariant();
+            return $"{os}-{architectureString}";
         }
 
         private void WriteLine(string format, params object[] args)
index db3fa3943bd410820117bc4bd985419ec52b5ed3..5d94f515d08bc32ffff96fae6d6bfd5e240db011 100644 (file)
@@ -29,7 +29,7 @@ namespace Microsoft.Diagnostics.Tools.Dump
         {
         }
 
-        public async Task<int> Collect(IConsole console, int processId, string output, DumpTypeOption type)
+        public async Task<int> Collect(IConsole console, int processId, string output, bool diag, DumpTypeOption type)
         {
             if (processId == 0) {
                 console.Error.WriteLine("ProcessId is required.");
@@ -64,7 +64,7 @@ namespace Microsoft.Diagnostics.Tools.Dump
                     DiagnosticsHelpers.DumpType dumpType = type == DumpTypeOption.Heap ? DiagnosticsHelpers.DumpType.WithHeap : DiagnosticsHelpers.DumpType.Normal;
 
                     // Send the command to the runtime to initiate the core dump
-                    var hr = DiagnosticsHelpers.GenerateCoreDump(processId, output, dumpType, diagnostics: false);
+                    var hr = DiagnosticsHelpers.GenerateCoreDump(processId, output, dumpType, diag);
                     if (hr != 0)
                     {
                         throw new InvalidOperationException($"Core dump generation FAILED 0x{hr:X8}");
index 957c987bcaadea69a9f0c3599bfb3a0a7de4cd5f..5f624fdc01def15a3b743e2d755927796763d9b2 100644 (file)
@@ -27,8 +27,8 @@ namespace Microsoft.Diagnostics.Tools.Dump
             new Command(
                 "collect", 
                 "Capture dumps from a process", 
-                new Option[] { ProcessIdOption(), OutputOption(), TypeOption() },
-                handler: CommandHandler.Create<IConsole, int, string, Dumper.DumpTypeOption>(new Dumper().Collect));
+                new Option[] { ProcessIdOption(), OutputOption(), DiagnosticLoggingOption(), TypeOption() },
+                handler: CommandHandler.Create<IConsole, int, string, bool, Dumper.DumpTypeOption>(new Dumper().Collect));
 
         private static Option ProcessIdOption() =>
             new Option(
@@ -36,7 +36,6 @@ namespace Microsoft.Diagnostics.Tools.Dump
                 "The process to collect a memory dump from.",
                 new Argument<int> { Name = "pid" });
 
-
         private static Option OutputOption() =>
             new Option(
                 new[] { "-o", "--output" },
@@ -45,6 +44,12 @@ namespace Microsoft.Diagnostics.Tools.Dump
 path and file name of the dump.",
                 new Argument<string>() { Name = "output_dump_path" });
 
+        private static Option DiagnosticLoggingOption() =>
+            new Option(
+                new[] { "--diag" }, 
+                "Enable dump collection diagnostic logging.",
+                new Argument<bool> { Name = "diag" });
+
         private static Option TypeOption() =>
             new Option(
                 "--type",
index 5baac43670513ff69304d4d8643e2af952e81cca..fa745dbe9c7a5b3d8921a9cb6763a94c92d5066b 100644 (file)
@@ -7,6 +7,8 @@ using System;
 using System.CommandLine;
 using System.CommandLine.Builder;
 using System.CommandLine.Invocation;
+using System.Reflection;
+using System.Runtime.InteropServices;
 using System.Threading.Tasks;
 
 namespace Microsoft.Diagnostics.Tools.SOS
@@ -28,19 +30,26 @@ namespace Microsoft.Diagnostics.Tools.SOS
             new Command(
                 "install", 
                 "Installs SOS and configures LLDB to load it on startup.", 
-                handler: CommandHandler.Create<IConsole>((console) => InvokeAsync(console, install: true)));
+                new Option[] { ArchitectureOption() },
+                handler: CommandHandler.Create<IConsole, Architecture?>((console, architecture) => InvokeAsync(console, architecture, install: true)));
+
+        private static Option ArchitectureOption() =>
+            new Option(
+                new[] { "--architecture" }, 
+                "The process to collect a memory dump from.",
+                new Argument<Architecture>() { Name = "architecture" });
 
         private static Command UninstallCommand() =>
             new Command(
                 "uninstall",
                 "Uninstalls SOS and reverts any configuration changes to LLDB.",
-                handler: CommandHandler.Create<IConsole>((console) => InvokeAsync(console, install: false)));
+                handler: CommandHandler.Create<IConsole>((console) => InvokeAsync(console, architecture: null, install: false)));
 
-        private static Task<int> InvokeAsync(IConsole console, bool install)
+        private static Task<int> InvokeAsync(IConsole console, Architecture? architecture, bool install)
         {
             try
             {
-                var sosInstaller = new InstallHelper((message) => console.Out.WriteLine(message));
+                var sosInstaller = new InstallHelper((message) => console.Out.WriteLine(message), architecture);
                 if (install) {
                     sosInstaller.Install();
                 }