| Index: tools/testing/dart/test_runner.dart
|
| diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
|
| index 06e3b0044ccbca3478285e86d7137b2a32231fb8..f0a21fdcee9a8e3d6b022f517d62bdf52d18684c 100644
|
| --- a/tools/testing/dart/test_runner.dart
|
| +++ b/tools/testing/dart/test_runner.dart
|
| @@ -1805,6 +1805,40 @@ Data removed due to excessive length
|
| }
|
| }
|
|
|
| +// Helper to get a list of all child pids for a parent process.
|
| +// The first element of the list is the parent pid.
|
| +Future<List<int>> _getPidList(pid, diagnostics) async {
|
| + var pid_list = [pid];
|
| + var lines;
|
| + var start_line = 0;
|
| + if (io.Platform.isLinux || io.Platform.isMacOS) {
|
| + var result = await io.Process.run("pgrep",
|
| + ["-P", "${pid_list[0]}"],
|
| + runInShell: true);
|
| + lines = result.stdout.split('\n');
|
| + } else if (io.Platform.isWindows) {
|
| + var result = await io.Process.run("wmic",
|
| + ["process", "where" , "(ParentProcessId=${pid_list[0]})",
|
| + "get", "ProcessId"],
|
| + runInShell: true);
|
| + lines = result.stdout.split('\n');
|
| + // Skip first line containing header "ProcessId".
|
| + start_line = 1;
|
| + } else {
|
| + assert(false);
|
| + }
|
| + if (lines.length > start_line) {
|
| + for (int i = start_line; i < lines.length; ++i) {
|
| + var pid = int.parse(lines[i], onError: (source) => null);
|
| + if (pid != null) pid_list.add(pid);
|
| + }
|
| + } else {
|
| + diagnostics.add("Could not find child pids");
|
| + diagnostics.addAll(lines);
|
| + }
|
| + return pid_list;
|
| +}
|
| +
|
| /**
|
| * A RunningProcess actually runs a test, getting the command lines from
|
| * its [TestCase], starting the test process (and first, a compilation
|
| @@ -1900,17 +1934,15 @@ class RunningProcess {
|
| timeoutHandler() async {
|
| timedOut = true;
|
| if (process != null) {
|
| - var executable, arguments;
|
| + var executable;
|
| if (io.Platform.isLinux) {
|
| executable = 'eu-stack';
|
| - arguments = ['-p ${process.pid}'];
|
| } else if (io.Platform.isMacOS) {
|
| // Try to print stack traces of the timed out process.
|
| // `sample` is a sampling profiler but we ask it sample for 1
|
| // second with a 4 second delay between samples so that we only
|
| // sample the threads once.
|
| executable = '/usr/bin/sample';
|
| - arguments = ['${process.pid}', '1', '4000', '-mayDie'];
|
| } else if (io.Platform.isWindows) {
|
| bool is_x64 = command.executable.contains("X64") ||
|
| command.executable.contains("SIMARM64");
|
| @@ -1923,15 +1955,32 @@ class RunningProcess {
|
| } else {
|
| diagnostics.add("win_sdk path not found");
|
| }
|
| + } else {
|
| + diagnostics.add("Capturing stack traces on"
|
| + "${io.Platform.operatingSystem} not supported");
|
| }
|
| -
|
| if (executable != null) {
|
| - try {
|
| - var result = await io.Process.run(executable, arguments);
|
| - diagnostics.addAll(result.stdout.split('\n'));
|
| - diagnostics.addAll(result.stderr.split('\n'));
|
| - } catch (error) {
|
| - diagnostics.add("Unable to capture stack traces: $error");
|
| + var pid_list = await _getPidList(process.pid, diagnostics);
|
| + diagnostics.add("Process list including children: $pid_list");
|
| + for (pid in pid_list) {
|
| + var arguments;
|
| + if (io.Platform.isLinux) {
|
| + arguments = ['-p $pid'];
|
| + } else if (io.Platform.isMacOS) {
|
| + arguments = ['$pid', '1', '4000', '-mayDie'];
|
| + } else if (io.Platform.isWindows) {
|
| + arguments = ['-p', '$pid', '-c', '!uniqstack;qd'];
|
| + } else {
|
| + assert(false);
|
| + }
|
| + diagnostics.add("Trying to capture stack trace for pid $pid");
|
| + try {
|
| + var result = await io.Process.run(executable, arguments);
|
| + diagnostics.addAll(result.stdout.split('\n'));
|
| + diagnostics.addAll(result.stderr.split('\n'));
|
| + } catch (error) {
|
| + diagnostics.add("Unable to capture stack traces: $error");
|
| + }
|
| }
|
| }
|
|
|
|
|