From 93b291fc01e0af0ea9ff87389694ce06b6409af7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Neum=C3=BCller?= Date: Sun, 5 Mar 2017 15:07:03 +0100 Subject: [PATCH] Let SuperDumpSelector.exe crash in case of an error (#25) improved superdumpselector.exe to re-used ProcessRunner. it should crash, if superdump.exe crashes. by that, we correctly show a failed analysis. --- build/conf/appsettings.json | 13 +++- .../ProcessRunner.cs | 14 ++-- .../ProcessRunnerException.cs | 14 ++++ src/SuperDump.Common/SuperDump.Common.csproj | 11 +++ src/SuperDump.sln | 14 ++++ src/SuperDumpSelector/Program.cs | 73 ++++++++----------- .../SuperDumpFailedException.cs | 19 +++++ .../SuperDumpSelector.csproj | 19 +++++ src/SuperDumpSelector/packages.config | 4 + .../Services/AnalysisService.cs | 41 ++++++----- src/SuperDumpService/SuperDumpService.csproj | 1 + 11 files changed, 157 insertions(+), 66 deletions(-) rename src/{SuperDumpService/Helpers => SuperDump.Common}/ProcessRunner.cs (80%) create mode 100644 src/SuperDump.Common/ProcessRunnerException.cs create mode 100644 src/SuperDump.Common/SuperDump.Common.csproj create mode 100644 src/SuperDumpSelector/SuperDumpFailedException.cs diff --git a/build/conf/appsettings.json b/build/conf/appsettings.json index 7810ec2..62cc209 100644 --- a/build/conf/appsettings.json +++ b/build/conf/appsettings.json @@ -20,8 +20,17 @@ "MaxConcurrentBundleExtraction": "4", "DumpsDir": "../../data/dumps/", "UploadDir": "../../data/uploads/", - "HangfireLocalDbDir": "../../data/hangfire/" - //"SuperDumpSelectorExePath": "" + "HangfireLocalDbDir": "../../data/hangfire/", + //"SuperDumpSelectorExePath": "../../SuperDumpSelector/SuperDumpSelector.exe", + "DeleteDumpAfterAnalysis": "false", + "DumpDownloadable": "true", + "MaxUploadSizeMB": "16000", + "IncludeOtherFilesInReport": "true", // if true, sibling files to a crashdump within a zip-file are copied to the dump-report directory. + "LinuxCommandTemplate": "myanalysis.sh {coredump} {outputjson}", + "BinPath": [ + "../SuperDump.DebugDiag/", + "../SuperDump.DebugDiag/bin/" + ] }, "ApplicationInsights": { "InstrumentationKey": "-" diff --git a/src/SuperDumpService/Helpers/ProcessRunner.cs b/src/SuperDump.Common/ProcessRunner.cs similarity index 80% rename from src/SuperDumpService/Helpers/ProcessRunner.cs rename to src/SuperDump.Common/ProcessRunner.cs index d0f8bdd..34de310 100644 --- a/src/SuperDumpService/Helpers/ProcessRunner.cs +++ b/src/SuperDump.Common/ProcessRunner.cs @@ -1,11 +1,9 @@ - - -using System; +using System; using System.Diagnostics; using System.IO; using System.Threading.Tasks; -namespace SuperDumpService.Helpers { +namespace SuperDump.Common { public class ProcessRunner : IDisposable { private readonly Process process; @@ -25,8 +23,14 @@ public ProcessRunner(string executable, DirectoryInfo workingDir, params string[ } public async Task Start() { + string info = $"starting process. exe: '{process.StartInfo.FileName}', args: '{process.StartInfo.Arguments}', workdir: '{process.StartInfo.WorkingDirectory}'"; + Console.WriteLine(info); await Task.Run(() => { - process.Start(); + try { + process.Start(); + } catch (Exception e) { + throw new ProcessRunnerException($"An exception occurred while starting a process: {info}", e); + } TrySetPriorityClass(process, ProcessPriorityClass.BelowNormal); StdOut = process.StandardOutput.ReadToEnd(); // important to do ReadToEnd before WaitForExit to avoid deadlock StdErr = process.StandardError.ReadToEnd(); diff --git a/src/SuperDump.Common/ProcessRunnerException.cs b/src/SuperDump.Common/ProcessRunnerException.cs new file mode 100644 index 0000000..8ff9da2 --- /dev/null +++ b/src/SuperDump.Common/ProcessRunnerException.cs @@ -0,0 +1,14 @@ +using System; + +namespace SuperDump.Common { + public class ProcessRunnerException : Exception { + public ProcessRunnerException() { + } + + public ProcessRunnerException(string message) : base(message) { + } + + public ProcessRunnerException(string message, Exception innerException) : base(message, innerException) { + } + } +} \ No newline at end of file diff --git a/src/SuperDump.Common/SuperDump.Common.csproj b/src/SuperDump.Common/SuperDump.Common.csproj new file mode 100644 index 0000000..e06471b --- /dev/null +++ b/src/SuperDump.Common/SuperDump.Common.csproj @@ -0,0 +1,11 @@ + + + + netstandard1.3 + + + + + + + \ No newline at end of file diff --git a/src/SuperDump.sln b/src/SuperDump.sln index e1d1d47..fba32a3 100644 --- a/src/SuperDump.sln +++ b/src/SuperDump.sln @@ -26,6 +26,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SuperDumpService", "SuperDu EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SuperDump.DebugDiag", "SuperDump.DebugDiag\SuperDump.DebugDiag.csproj", "{7AD98161-6822-47E6-8A68-9374D854599F}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SuperDump.Common", "SuperDump.Common\SuperDump.Common.csproj", "{68D2B1C2-740B-48B4-8CE0-88D8B9437541}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -108,6 +110,18 @@ Global {7AD98161-6822-47E6-8A68-9374D854599F}.Release|x64.Build.0 = Release|Any CPU {7AD98161-6822-47E6-8A68-9374D854599F}.Release|x86.ActiveCfg = Release|Any CPU {7AD98161-6822-47E6-8A68-9374D854599F}.Release|x86.Build.0 = Release|Any CPU + {68D2B1C2-740B-48B4-8CE0-88D8B9437541}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {68D2B1C2-740B-48B4-8CE0-88D8B9437541}.Debug|Any CPU.Build.0 = Debug|Any CPU + {68D2B1C2-740B-48B4-8CE0-88D8B9437541}.Debug|x64.ActiveCfg = Debug|x64 + {68D2B1C2-740B-48B4-8CE0-88D8B9437541}.Debug|x64.Build.0 = Debug|x64 + {68D2B1C2-740B-48B4-8CE0-88D8B9437541}.Debug|x86.ActiveCfg = Debug|x86 + {68D2B1C2-740B-48B4-8CE0-88D8B9437541}.Debug|x86.Build.0 = Debug|x86 + {68D2B1C2-740B-48B4-8CE0-88D8B9437541}.Release|Any CPU.ActiveCfg = Release|Any CPU + {68D2B1C2-740B-48B4-8CE0-88D8B9437541}.Release|Any CPU.Build.0 = Release|Any CPU + {68D2B1C2-740B-48B4-8CE0-88D8B9437541}.Release|x64.ActiveCfg = Release|x64 + {68D2B1C2-740B-48B4-8CE0-88D8B9437541}.Release|x64.Build.0 = Release|x64 + {68D2B1C2-740B-48B4-8CE0-88D8B9437541}.Release|x86.ActiveCfg = Release|x86 + {68D2B1C2-740B-48B4-8CE0-88D8B9437541}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/SuperDumpSelector/Program.cs b/src/SuperDumpSelector/Program.cs index 77cbd85..40c3c0d 100644 --- a/src/SuperDumpSelector/Program.cs +++ b/src/SuperDumpSelector/Program.cs @@ -5,6 +5,8 @@ using System.Threading; using System.Configuration; using System.Reflection; +using System.Threading.Tasks; +using SuperDump.Common; namespace SuperDumpSelector { public static class Program { @@ -26,53 +28,40 @@ public static void Main(string[] args) { Console.WriteLine(Environment.CurrentDirectory); if (File.Exists(dumpfile)) { - var p = new Process(); - using (DataTarget target = DataTarget.LoadCrashDump(dumpfile)) { - if (target.PointerSize == 8) { - p.StartInfo.FileName = ResolvePath(ConfigurationManager.AppSettings["superdumpx64"]); - if (!File.Exists(p.StartInfo.FileName)) p.StartInfo.FileName = ResolvePath(ConfigurationManager.AppSettings["superdumpx64_deployment"]); - Console.WriteLine("detected x64 dump, selecting 64-bit build of SuperDump ..."); - } else if (target.PointerSize == 4) { - p.StartInfo.FileName = ResolvePath(ConfigurationManager.AppSettings["superdumpx86"]); - if (!File.Exists(p.StartInfo.FileName)) p.StartInfo.FileName = ResolvePath(ConfigurationManager.AppSettings["superdumpx86_deployment"]); - Console.WriteLine("detected x86 dump, selecting 32-bit build of SuperDump ..."); - } else { - Console.WriteLine("target dump architecture is different than x64 or x86, this is not yet supported!"); - } - } - p.StartInfo.Arguments = $"{dumpfile} {outputfile}"; - p.StartInfo.UseShellExecute = false; - p.StartInfo.RedirectStandardOutput = true; - p.StartInfo.WorkingDirectory = Path.GetDirectoryName(p.StartInfo.FileName); - - try { - Console.WriteLine($"launching '{p.StartInfo.FileName}' '{p.StartInfo.Arguments}'"); - Console.WriteLine($"working dir: '{p.StartInfo.WorkingDirectory}'"); - p.Start(); - TrySetPriorityClass(p, ProcessPriorityClass.BelowNormal); - Console.WriteLine("... analyzing"); - do { - Console.WriteLine(p.StandardOutput.ReadLine()); - Thread.Sleep(15); - } while (!p.HasExited); - - Console.Write(p.StandardOutput.ReadToEnd()); - } catch (Exception ex) { - Console.WriteLine("Exception thrown, maybe you have not built SuperDump in right bitness yet? Build and try again"); - - Console.WriteLine(ex.Message); - throw; - } + var superDumpPathInfo = FindSuperDumpPath(dumpfile); + RunSuperDump(superDumpPathInfo, dumpfile, outputfile).Wait(); } else { throw new FileNotFoundException($"Dump file was not found at {dumpfile}. Please try again"); } } - private static void TrySetPriorityClass(Process process, ProcessPriorityClass priority) { - try { - process.PriorityClass = priority; - } catch (Exception) { - // this might be disallowed, e.g. in Azure WebApps + private static FileInfo FindSuperDumpPath(string dumpfile) { + using (DataTarget target = DataTarget.LoadCrashDump(dumpfile)) { + string superDumpPath; ; + if (target.PointerSize == 8) { + superDumpPath = ResolvePath(ConfigurationManager.AppSettings["superdumpx64"]); + if (!File.Exists(superDumpPath)) superDumpPath = ResolvePath(ConfigurationManager.AppSettings["superdumpx64_deployment"]); + Console.WriteLine("detected x64 dump, selecting 64-bit build of SuperDump ..."); + } else if (target.PointerSize == 4) { + superDumpPath = ResolvePath(ConfigurationManager.AppSettings["superdumpx86"]); + if (!File.Exists(superDumpPath)) superDumpPath = ResolvePath(ConfigurationManager.AppSettings["superdumpx86_deployment"]); + Console.WriteLine("detected x86 dump, selecting 32-bit build of SuperDump ..."); + } else { + throw new NotSupportedException("target dump architecture is different than x64 or x86, this is not yet supported!"); + } + return new FileInfo(superDumpPath); + } + } + + private static async Task RunSuperDump(FileInfo superDumpPath, string dumpfile, string outputfile) { + using (var process = await ProcessRunner.Run(superDumpPath.FullName, superDumpPath.Directory, $"{dumpfile} {outputfile}")) { + //TrySetPriorityClass(process, ProcessPriorityClass.BelowNormal); + Console.WriteLine($"stdout: {process.StdOut}"); + Console.WriteLine($"stderr: {process.StdErr}"); + Console.WriteLine($"exitcode: {process.ExitCode}"); + if (process.ExitCode != 0) { + throw new SuperDumpFailedException(process.StdErr); + } } } diff --git a/src/SuperDumpSelector/SuperDumpFailedException.cs b/src/SuperDumpSelector/SuperDumpFailedException.cs new file mode 100644 index 0000000..95175b5 --- /dev/null +++ b/src/SuperDumpSelector/SuperDumpFailedException.cs @@ -0,0 +1,19 @@ +using System; +using System.Runtime.Serialization; + +namespace SuperDumpSelector { + [Serializable] + internal class SuperDumpFailedException : Exception { + public SuperDumpFailedException() { + } + + public SuperDumpFailedException(string message) : base(message) { + } + + public SuperDumpFailedException(string message, Exception innerException) : base(message, innerException) { + } + + protected SuperDumpFailedException(SerializationInfo info, StreamingContext context) : base(info, context) { + } + } +} \ No newline at end of file diff --git a/src/SuperDumpSelector/SuperDumpSelector.csproj b/src/SuperDumpSelector/SuperDumpSelector.csproj index 2b46704..c8014a4 100644 --- a/src/SuperDumpSelector/SuperDumpSelector.csproj +++ b/src/SuperDumpSelector/SuperDumpSelector.csproj @@ -59,7 +59,19 @@ + + ..\packages\System.Console.4.3.0\lib\net46\System.Console.dll + + + ..\packages\System.Diagnostics.Process.4.3.0\lib\net46\System.Diagnostics.Process.dll + + + ..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll + + + ..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll + @@ -70,6 +82,7 @@ + @@ -87,6 +100,12 @@ false + + + {68D2B1C2-740B-48B4-8CE0-88D8B9437541} + SuperDump.Common + +