/// <summary> /// Invoked when a timeout occurs and we need to dump all of the test processes and shut down /// the runnner. /// </summary> private static async Task HandleTimeout(Options options, CancellationToken cancellationToken) { var procDumpFilePath = Path.Combine(options.ProcDumpPath, "procdump.exe"); async Task DumpProcess(Process targetProcess, string dumpFilePath) { Console.Write($"Dumping {targetProcess.ProcessName} {targetProcess.Id} to {dumpFilePath} ... "); try { var args = $"-accepteula -ma {targetProcess.Id} {dumpFilePath}"; var processTask = ProcessRunner.RunProcessAsync(procDumpFilePath, args, cancellationToken); var processOutput = await processTask; // The exit code for procdump doesn't obey standard windows rules. It will return non-zero // for succesful cases (possibly returning the count of dumps that were written). Best // backup is to test for the dump file being present. if (File.Exists(dumpFilePath)) { Console.WriteLine("succeeded"); } else { Console.WriteLine($"FAILED with {processOutput.ExitCode}"); Console.WriteLine($"{procDumpFilePath} {args}"); Console.WriteLine(string.Join(Environment.NewLine, processOutput.OutputLines)); } } catch (Exception ex) when(!cancellationToken.IsCancellationRequested) { Console.WriteLine("FAILED"); Console.WriteLine(ex.Message); Logger.Log("Failed to dump process", ex); } } Console.WriteLine("Roslyn Error: test timeout exceeded, dumping remaining processes"); if (!string.IsNullOrEmpty(options.ProcDumpPath)) { var dumpDir = options.LogFilePath != null ? Path.GetDirectoryName(options.LogFilePath) : Directory.GetCurrentDirectory(); Console.WriteLine($"Dump file location is {dumpDir}"); var counter = 0; foreach (var proc in ProcessUtil.GetProcessTree(Process.GetCurrentProcess()).OrderBy(x => x.ProcessName)) { var dumpFilePath = Path.Combine(dumpDir, $"{proc.ProcessName}-{counter}.dmp"); await DumpProcess(proc, dumpFilePath); counter++; } } else { Console.WriteLine("Could not locate procdump"); } WriteLogFile(options); }
/// <summary> /// Invoked when a timeout occurs and we need to dump all of the test processes and shut down /// the runnner. /// </summary> private static async Task HandleTimeout(Options options, CancellationToken cancellationToken) { async Task DumpProcess(Process targetProcess, string procDumpExeFilePath, string dumpFilePath) { var name = targetProcess.ProcessName; // Our space for saving dump files is limited. Skip dumping for processes that won't contribute // to bug investigations. if (name == "procdump" || name == "conhost") { return; } ConsoleUtil.Write($"Dumping {name} {targetProcess.Id} to {dumpFilePath} ... "); try { var args = $"-accepteula -ma {targetProcess.Id} {dumpFilePath}"; var processInfo = ProcessRunner.CreateProcess(procDumpExeFilePath, args, cancellationToken: cancellationToken); var processOutput = await processInfo.Result; // The exit code for procdump doesn't obey standard windows rules. It will return non-zero // for successful cases (possibly returning the count of dumps that were written). Best // backup is to test for the dump file being present. if (File.Exists(dumpFilePath)) { ConsoleUtil.WriteLine($"succeeded ({new FileInfo(dumpFilePath).Length} bytes)"); } else { ConsoleUtil.WriteLine($"FAILED with {processOutput.ExitCode}"); ConsoleUtil.WriteLine($"{procDumpExeFilePath} {args}"); ConsoleUtil.WriteLine(string.Join(Environment.NewLine, processOutput.OutputLines)); } } catch (Exception ex) when(!cancellationToken.IsCancellationRequested) { ConsoleUtil.WriteLine("FAILED"); ConsoleUtil.WriteLine(ex.Message); Logger.Log("Failed to dump process", ex); } } ConsoleUtil.WriteLine("Roslyn Error: test timeout exceeded, dumping remaining processes"); var procDumpInfo = GetProcDumpInfo(options); if (procDumpInfo != null) { 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++; } } else { ConsoleUtil.WriteLine("Could not locate procdump"); } WriteLogFile(options); }