Skip to content

Commit

Permalink
Let SuperDumpSelector.exe crash in case of an error (#25)
Browse files Browse the repository at this point in the history
improved superdumpselector.exe to re-used ProcessRunner. it should crash, if superdump.exe crashes. by that, we correctly show a failed analysis.
  • Loading branch information
discostu105 authored Mar 5, 2017
1 parent e84a64e commit 93b291f
Show file tree
Hide file tree
Showing 11 changed files with 157 additions and 66 deletions.
13 changes: 11 additions & 2 deletions build/conf/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": "-"
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -25,8 +23,14 @@ public ProcessRunner(string executable, DirectoryInfo workingDir, params string[
}

public async Task<ProcessRunner> 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();
Expand Down
14 changes: 14 additions & 0 deletions src/SuperDump.Common/ProcessRunnerException.cs
Original file line number Diff line number Diff line change
@@ -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) {
}
}
}
11 changes: 11 additions & 0 deletions src/SuperDump.Common/SuperDump.Common.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
</ItemGroup>

</Project>
14 changes: 14 additions & 0 deletions src/SuperDump.sln
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
73 changes: 31 additions & 42 deletions src/SuperDumpSelector/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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);
}
}
}

Expand Down
19 changes: 19 additions & 0 deletions src/SuperDumpSelector/SuperDumpFailedException.cs
Original file line number Diff line number Diff line change
@@ -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) {
}
}
}
19 changes: 19 additions & 0 deletions src/SuperDumpSelector/SuperDumpSelector.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,19 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Console, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Console.4.3.0\lib\net46\System.Console.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Diagnostics.Process, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Diagnostics.Process.4.3.0\lib\net46\System.Diagnostics.Process.dll</HintPath>
</Reference>
<Reference Include="System.IO.FileSystem, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath>
</Reference>
<Reference Include="System.IO.FileSystem.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
Expand All @@ -70,6 +82,7 @@
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SuperDumpFailedException.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
Expand All @@ -87,6 +100,12 @@
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SuperDump.Common\SuperDump.Common.csproj">
<Project>{68D2B1C2-740B-48B4-8CE0-88D8B9437541}</Project>
<Name>SuperDump.Common</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand Down
4 changes: 4 additions & 0 deletions src/SuperDumpSelector/packages.config
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Diagnostics.Runtime" version="0.8.31-beta" targetFramework="net46" />
<package id="System.Console" version="4.3.0" targetFramework="net46" />
<package id="System.Diagnostics.Process" version="4.3.0" targetFramework="net46" />
<package id="System.IO.FileSystem" version="4.3.0" targetFramework="net46" />
<package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net46" />
</packages>
41 changes: 24 additions & 17 deletions src/SuperDumpService/Services/AnalysisService.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
using Microsoft.Extensions.Options;
using SuperDumpService.Helpers;
using SuperDumpService.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using SuperDump.Common;
using SuperDumpService.Helpers;
using SuperDumpService.Models;

namespace SuperDumpService.Services {
public class AnalysisService {
Expand Down Expand Up @@ -80,17 +79,25 @@ private async Task RunDebugDiagAnalysis(DumpMetainfo dumpInfo, DirectoryInfo wor
string reportFilePath = Path.Combine(pathHelper.GetDumpDirectory(dumpInfo.BundleId, dumpInfo.DumpId), "DebugDiagAnalysis.mht");
string debugDiagExe = "SuperDump.DebugDiag.exe";

Console.WriteLine($"launching '{debugDiagExe}' --dump='{dumpFilePath}' --out='{reportFilePath}' --overwrite");
using (var process = await ProcessRunner.Run(debugDiagExe, workingDir,
$"--dump=\"{dumpFilePath}\"",
$"--out=\"{reportFilePath}\"",
"--overwrite")) {
string log = $"debugDiagExe exited with error code {process.ExitCode}" +
$"{Environment.NewLine}{Environment.NewLine}stdout:{Environment.NewLine}{process.StdOut}" +
$"{Environment.NewLine}{Environment.NewLine}stderr:{Environment.NewLine}{process.StdErr}";
Console.WriteLine(log);
File.WriteAllText(Path.Combine(pathHelper.GetDumpDirectory(dumpInfo.BundleId, dumpInfo.DumpId), "superdump.debugdiag.log"), log);
dumpRepo.AddFile(dumpInfo.BundleId, dumpInfo.DumpId, "DebugDiagAnalysis.mht", SDFileType.DebugDiagResult);
try {
using (var process = await ProcessRunner.Run(debugDiagExe, workingDir,
$"--dump=\"{dumpFilePath}\"",
$"--out=\"{reportFilePath}\"",
"--overwrite")) {
string log = $"debugDiagExe exited with error code {process.ExitCode}" +
$"{Environment.NewLine}{Environment.NewLine}stdout:{Environment.NewLine}{process.StdOut}" +
$"{Environment.NewLine}{Environment.NewLine}stderr:{Environment.NewLine}{process.StdErr}";
Console.WriteLine(log);
File.WriteAllText(Path.Combine(pathHelper.GetDumpDirectory(dumpInfo.BundleId, dumpInfo.DumpId), "superdump.debugdiag.log"), log);
dumpRepo.AddFile(dumpInfo.BundleId, dumpInfo.DumpId, "DebugDiagAnalysis.mht", SDFileType.DebugDiagResult);
}
} catch (ProcessRunnerException e) {
if (e.InnerException is FileNotFoundException) {
Console.Error.WriteLine($"{debugDiagExe} not found. Check BinPath setting in appsettings.json.");
} else {
Console.Error.WriteLine($"Error during DebugDiag analyis: {e}");
}
// do not abort analysis.
}
}

Expand Down
1 change: 1 addition & 0 deletions src/SuperDumpService/SuperDumpService.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
<DotNetCliToolReference Include="BundlerMinifier.Core" Version="2.2.301" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SuperDump.Common\SuperDump.Common.csproj" />
<ProjectReference Include="..\SuperDumpModels\SuperDumpModels.csproj" />
</ItemGroup>
</Project>

0 comments on commit 93b291f

Please sign in to comment.