Skip to content
Permalink
Browse files

Write secondary process dumps to a separate directory

  • Loading branch information...
sharwell committed May 14, 2019
1 parent 8a40391 commit 80cdb06828c6773def553c9c3b3c3dcae9e5652d
@@ -70,6 +70,15 @@ jobs:
continueOnError: true
condition: not(succeeded())

- task: PublishBuildArtifacts@1
displayName: Publish Secondary Logs
inputs:
PathtoPublish: '$(Build.SourcesDirectory)\artifacts\log2\$(_configuration)'
ArtifactName: '$(System.JobAttempt)-Secondary Logs $(_configuration) $(_completionName) $(Build.BuildNumber)'
publishLocation: Container
continueOnError: true
condition: not(succeeded())

- task: PublishBuildArtifacts@1
displayName: Publish Screenshots
inputs:
@@ -345,6 +345,8 @@ function TestUsingOptimizedRunner() {
$env:ROSLYN_TEST_LEGACY_COMPLETION = "true"
}

$secondaryLogDir = Join-Path (Join-Path $ArtifactsDir "log2") $configuration
Create-Directory $secondaryLogDir
$testResultsDir = Join-Path $ArtifactsDir "TestResults\$configuration"
$binDir = Join-Path $ArtifactsDir "bin"
$runTests = GetProjectOutputBinary "RunTests.exe"
@@ -358,6 +360,7 @@ function TestUsingOptimizedRunner() {
$args = "`"$xunitDir`""
$args += " `"-out:$testResultsDir`""
$args += " `"-logs:$LogDir`""
$args += " `"-secondaryLogs:$secondaryLogDir`""
$args += " -nocache"
$args += " -tfm:net472"

@@ -91,6 +91,11 @@ internal class Options
/// </summary>
public string LogFilesOutputDirectory { get; set; }

/// <summary>
/// Directory to hold secondary dump files created while running tests.
/// </summary>
public string LogFilesSecondaryOutputDirectory { get; set; }

internal static Options Parse(string[] args)
{
if (args == null || args.Any(a => a == null) || args.Length < 2)
@@ -154,6 +159,11 @@ bool isOption(string argument, string optionName, out string value)
opt.LogFilesOutputDirectory = logsPath;
index++;
}
else if (isOption(current, "-secondaryLogs", out string secondaryLogsPath))
{
opt.LogFilesSecondaryOutputDirectory = secondaryLogsPath;
index++;
}
else if (isOption(current, "-display", out value))
{
if (Enum.TryParse(value, ignoreCase: true, result: out Display display))
@@ -238,6 +248,9 @@ bool isOption(string argument, string optionName, out string value)
opt.LogFilesOutputDirectory = opt.TestResultXmlOutputDirectory;
}

// If we weren't passed both -secondaryLogs and -logs but just -logs (or -out), use the same value for -secondaryLogs too.
opt.LogFilesSecondaryOutputDirectory ??= opt.LogFilesOutputDirectory;

opt.Assemblies = args.Skip(index).ToList();
return allGood ? opt : null;
}
@@ -11,22 +11,27 @@ namespace RunTests
{
private const string KeyProcDumpFilePath = "ProcDumpFilePath";
private const string KeyProcDumpDirectory = "ProcDumpOutputPath";
private const string KeyProcDumpSecondaryDirectory = "ProcDumpSecondaryOutputPath";

internal string ProcDumpFilePath { get; }
internal string DumpDirectory { get; }
internal string SecondaryDumpDirectory { get; }

internal ProcDumpInfo(string procDumpFilePath, string dumpDirectory)
internal ProcDumpInfo(string procDumpFilePath, string dumpDirectory, string secondaryDumpDirectory)
{
Debug.Assert(Path.IsPathRooted(procDumpFilePath));
Debug.Assert(Path.IsPathRooted(dumpDirectory));
Debug.Assert(Path.IsPathRooted(secondaryDumpDirectory));
ProcDumpFilePath = procDumpFilePath;
DumpDirectory = dumpDirectory;
SecondaryDumpDirectory = secondaryDumpDirectory;
}

internal void WriteEnvironmentVariables(Dictionary<string, string> environment)
{
environment[KeyProcDumpFilePath] = ProcDumpFilePath;
environment[KeyProcDumpDirectory] = DumpDirectory;
environment[KeyProcDumpSecondaryDirectory] = SecondaryDumpDirectory;
}

internal static ProcDumpInfo? ReadFromEnvironment()
@@ -35,13 +40,14 @@ internal void WriteEnvironmentVariables(Dictionary<string, string> environment)

var procDumpFilePath = Environment.GetEnvironmentVariable(KeyProcDumpFilePath);
var dumpDirectory = Environment.GetEnvironmentVariable(KeyProcDumpDirectory);
var secondaryDumpDirectory = Environment.GetEnvironmentVariable(KeyProcDumpSecondaryDirectory);

if (!validate(procDumpFilePath) || !validate(dumpDirectory))
if (!validate(procDumpFilePath) || !validate(dumpDirectory) || !validate(secondaryDumpDirectory))
{
return null;
}

return new ProcDumpInfo(procDumpFilePath, dumpDirectory);
return new ProcDumpInfo(procDumpFilePath, dumpDirectory, secondaryDumpDirectory);
}
}

@@ -20,6 +20,11 @@ namespace RunTests
{
internal sealed partial class Program
{
private static readonly ImmutableHashSet<string> PrimaryProcessNames = ImmutableHashSet.Create(
StringComparer.OrdinalIgnoreCase,
"devenv",
"xunit.console.x86");

internal const int ExitSuccess = 0;
internal const int ExitFailure = 1;

@@ -223,10 +228,12 @@ async Task DumpProcess(Process targetProcess, string procDumpExeFilePath, string
var procDumpInfo = GetProcDumpInfo(options);
if (procDumpInfo != null)
{
var dumpDir = procDumpInfo.Value.DumpDirectory;
var counter = 0;
foreach (var proc in ProcessUtil.GetProcessTree(Process.GetCurrentProcess()).OrderBy(x => x.ProcessName))
{
var dumpDir = PrimaryProcessNames.Contains(proc.ProcessName)
? procDumpInfo.Value.DumpDirectory
: procDumpInfo.Value.SecondaryDumpDirectory;
var dumpFilePath = Path.Combine(dumpDir, $"{proc.ProcessName}-{counter}.dmp");
await DumpProcess(proc, procDumpInfo.Value.ProcDumpFilePath, dumpFilePath);
counter++;
@@ -244,7 +251,7 @@ async Task DumpProcess(Process targetProcess, string procDumpExeFilePath, string
{
if (!string.IsNullOrEmpty(options.ProcDumpDirectory))
{
return new ProcDumpInfo(Path.Combine(options.ProcDumpDirectory, "procdump.exe"), options.LogFilesOutputDirectory);
return new ProcDumpInfo(Path.Combine(options.ProcDumpDirectory, "procdump.exe"), options.LogFilesOutputDirectory, options.LogFilesSecondaryOutputDirectory);
}

return null;

0 comments on commit 80cdb06

Please sign in to comment.
You can’t perform that action at this time.