diff --git a/dev/devicelab/lib/framework/running_processes.dart b/dev/devicelab/lib/framework/running_processes.dart index 0efb77c4a4e..7ff6f8a6131 100644 --- a/dev/devicelab/lib/framework/running_processes.dart +++ b/dev/devicelab/lib/framework/running_processes.dart @@ -14,7 +14,7 @@ class RunningProcessInfo { assert(commandLine != null); final String commandLine; - final int pid; + final String pid; final DateTime creationDate; @override @@ -47,7 +47,7 @@ class RunningProcessInfo { } } -Future killProcess(int pid, {ProcessManager processManager}) async { +Future killProcess(String pid, {ProcessManager processManager}) async { assert(pid != null, 'Must specify a pid to kill'); processManager ??= const LocalProcessManager(); ProcessResult result; @@ -55,14 +55,14 @@ Future killProcess(int pid, {ProcessManager processManager}) async { result = await processManager.run([ 'taskkill.exe', '/pid', - pid.toString(), + pid, '/f', ]); } else { result = await processManager.run([ 'kill', '-9', - pid.toString(), + pid, ]); } return result.exitCode == 0; @@ -163,7 +163,7 @@ Iterable processPowershellOutput(String output) sync* { time = '${hours + 12}${time.substring(2)}'; } - final int pid = int.parse(line.substring(0, processIdHeaderSize).trim()); + final String pid = line.substring(0, processIdHeaderSize).trim(); final DateTime creationDate = DateTime.parse('$year-$month-${day}T$time'); final String commandLine = line.substring(commandLineHeaderStart).trim(); yield RunningProcessInfo(pid, creationDate, commandLine); @@ -254,7 +254,7 @@ Iterable processPsOutput( final DateTime creationDate = DateTime.parse('$year-$month-${day}T$time'); line = line.substring(24).trim(); final int nextSpace = line.indexOf(' '); - final int pid = int.parse(line.substring(0, nextSpace)); + final String pid = line.substring(0, nextSpace); final String commandLine = line.substring(nextSpace + 1); yield RunningProcessInfo(pid, creationDate, commandLine); } diff --git a/dev/devicelab/lib/tasks/web_dev_mode_tests.dart b/dev/devicelab/lib/tasks/web_dev_mode_tests.dart index af96e095bc4..78cf94eadea 100644 --- a/dev/devicelab/lib/tasks/web_dev_mode_tests.dart +++ b/dev/devicelab/lib/tasks/web_dev_mode_tests.dart @@ -9,6 +9,7 @@ import 'dart:io'; import 'package:path/path.dart' as path; import '../framework/framework.dart'; +import '../framework/running_processes.dart'; import '../framework/utils.dart'; final Directory _editedFlutterGalleryDir = dir(path.join(Directory.systemTemp.path, 'edited_flutter_gallery')); @@ -20,119 +21,140 @@ TaskFunction createWebDevModeTest() { '--hot', '-d', 'chrome', '--verbose', '--resident', '--target=lib/main.dart', ]; int hotRestartCount = 0; - await inDirectory(flutterDirectory, () async { - rmTree(_editedFlutterGalleryDir); - mkdirs(_editedFlutterGalleryDir); - recursiveCopy(flutterGalleryDir, _editedFlutterGalleryDir); - await inDirectory(_editedFlutterGalleryDir, () async { - { - final Process packagesGet = await startProcess( - path.join(flutterDirectory.path, 'bin', 'flutter'), - ['packages', 'get'], - environment: { - 'FLUTTER_WEB': 'true', - }, - ); - await packagesGet.exitCode; - final Process process = await startProcess( - path.join(flutterDirectory.path, 'bin', 'flutter'), - flutterCommandArgs('run', options), - environment: { - 'FLUTTER_WEB': 'true', - }, - ); + String chromeProcessName; + if (Platform.isMacOS) { + chromeProcessName = 'Chrome'; + } else if (Platform.isLinux) { + chromeProcessName = 'chrome'; + } else if (Platform.isWindows) { + chromeProcessName = 'chrome.exe'; + } + final Set beforeChromeProcesses = await getRunningProcesses(processName: chromeProcessName) + .map((RunningProcessInfo info) => info.pid) + .toSet(); + try { + await inDirectory(flutterDirectory, () async { + rmTree(_editedFlutterGalleryDir); + mkdirs(_editedFlutterGalleryDir); + recursiveCopy(flutterGalleryDir, _editedFlutterGalleryDir); + await inDirectory(_editedFlutterGalleryDir, () async { + { + final Process packagesGet = await startProcess( + path.join(flutterDirectory.path, 'bin', 'flutter'), + ['packages', 'get'], + environment: { + 'FLUTTER_WEB': 'true', + }, + ); + await packagesGet.exitCode; + final Process process = await startProcess( + path.join(flutterDirectory.path, 'bin', 'flutter'), + flutterCommandArgs('run', options), + environment: { + 'FLUTTER_WEB': 'true', + }, + ); - final Completer stdoutDone = Completer(); - final Completer stderrDone = Completer(); - process.stdout - .transform(utf8.decoder) - .transform(const LineSplitter()) - .listen((String line) { - if (line.contains('To hot restart')) { - process.stdin.write('R'); - } - if (line.contains('Restarted')) { - if (hotRestartCount == 0) { - // Update the file and reload again. - final File appDartSource = file(path.join( - _editedFlutterGalleryDir.path, 'lib/gallery/app.dart', - )); - appDartSource.writeAsStringSync( - appDartSource.readAsStringSync().replaceFirst( - "'Flutter Gallery'", "'Updated Flutter Gallery'", - ) - ); - process.stdin.writeln('R'); - ++hotRestartCount; - } else { - // Quit after second hot restart. + final Completer stdoutDone = Completer(); + final Completer stderrDone = Completer(); + process.stdout + .transform(utf8.decoder) + .transform(const LineSplitter()) + .listen((String line) { + if (line.contains('To hot restart')) { + process.stdin.write('R'); + } + if (line.contains('Restarted')) { + if (hotRestartCount == 0) { + // Update the file and reload again. + final File appDartSource = file(path.join( + _editedFlutterGalleryDir.path, 'lib/gallery/app.dart', + )); + appDartSource.writeAsStringSync( + appDartSource.readAsStringSync().replaceFirst( + "'Flutter Gallery'", "'Updated Flutter Gallery'", + ) + ); + process.stdin.writeln('R'); + ++hotRestartCount; + } else { + // Quit after second hot restart. + process.stdin.writeln('q'); + } + } + print('stdout: $line'); + }, onDone: () { + stdoutDone.complete(); + }); + process.stderr + .transform(utf8.decoder) + .transform(const LineSplitter()) + .listen((String line) { + print('stderr: $line'); + }, onDone: () { + stderrDone.complete(); + }); + + await Future.wait(>[ + stdoutDone.future, + stderrDone.future, + ]); + await process.exitCode; + + } + + // Start `flutter run` again to make sure it loads from the previous + // state. dev compilers loads up from previously compiled JavaScript. + { + final Process process = await startProcess( + path.join(flutterDirectory.path, 'bin', 'flutter'), + flutterCommandArgs('run', options), + environment: { + 'FLUTTER_WEB': 'true', + }, + ); + final Completer stdoutDone = Completer(); + final Completer stderrDone = Completer(); + process.stdout + .transform(utf8.decoder) + .transform(const LineSplitter()) + .listen((String line) { + if (line.contains('To hot restart')) { + process.stdin.write('R'); + } + if (line.contains('Restarted')) { process.stdin.writeln('q'); } - } - print('stdout: $line'); - }, onDone: () { - stdoutDone.complete(); - }); - process.stderr - .transform(utf8.decoder) - .transform(const LineSplitter()) - .listen((String line) { - print('stderr: $line'); - }, onDone: () { - stderrDone.complete(); - }); + print('stdout: $line'); + }, onDone: () { + stdoutDone.complete(); + }); + process.stderr + .transform(utf8.decoder) + .transform(const LineSplitter()) + .listen((String line) { + print('stderr: $line'); + }, onDone: () { + stderrDone.complete(); + }); - await Future.wait(>[ - stdoutDone.future, - stderrDone.future, - ]); - await process.exitCode; - - } - - // Start `flutter run` again to make sure it loads from the previous - // state. dev compilers loads up from previously compiled JavaScript. - { - final Process process = await startProcess( - path.join(flutterDirectory.path, 'bin', 'flutter'), - flutterCommandArgs('run', options), - environment: { - 'FLUTTER_WEB': 'true', - }, - ); - final Completer stdoutDone = Completer(); - final Completer stderrDone = Completer(); - process.stdout - .transform(utf8.decoder) - .transform(const LineSplitter()) - .listen((String line) { - if (line.contains('To hot restart')) { - process.stdin.write('R'); - } - if (line.contains('Restarted')) { - process.stdin.writeln('q'); - } - print('stdout: $line'); - }, onDone: () { - stdoutDone.complete(); - }); - process.stderr - .transform(utf8.decoder) - .transform(const LineSplitter()) - .listen((String line) { - print('stderr: $line'); - }, onDone: () { - stderrDone.complete(); - }); - - await Future.wait(>[ - stdoutDone.future, - stderrDone.future, - ]); - await process.exitCode; - } + await Future.wait(>[ + stdoutDone.future, + stderrDone.future, + ]); + await process.exitCode; + } + }); }); - }); + } finally { + final Set afterChromeProcesses = await getRunningProcesses(processName: chromeProcessName) + .map((RunningProcessInfo info) => info.pid) + .toSet(); + final Set newProcesses = afterChromeProcesses.difference(beforeChromeProcesses); + for (String processId in newProcesses) { + await killProcess(processId); + } + } if (hotRestartCount != 1) { return TaskResult.failure(null); } diff --git a/dev/devicelab/test/running_processes_test.dart b/dev/devicelab/test/running_processes_test.dart index 395ada4673f..5aa9f37878b 100644 --- a/dev/devicelab/test/running_processes_test.dart +++ b/dev/devicelab/test/running_processes_test.dart @@ -24,17 +24,17 @@ ProcessId CreationDate CommandLine results, equals([ RunningProcessInfo( - 6552, + '6552', DateTime(2019, 7, 3, 17, 0, 27), r'"C:\tools\dart-sdk\bin\dart.exe" .\bin\agent.dart ci', ), RunningProcessInfo( - 6553, + '6553', DateTime(2019, 7, 3, 22, 0, 27), r'"C:\tools\dart-sdk1\bin\dart.exe" .\bin\agent.dart ci', ), RunningProcessInfo( - 6554, + '6554', DateTime(2019, 7, 3, 11, 0, 27), r'"C:\tools\dart-sdk2\bin\dart.exe" .\bin\agent.dart ci', ), @@ -54,12 +54,12 @@ Sat Mar 9 20:13:00 2019 49 /usr/sbin/syslogd results, equals([ RunningProcessInfo( - 1, + '1', DateTime(2019, 3, 9, 20, 12, 47), '/sbin/launchd', ), RunningProcessInfo( - 49, + '49', DateTime(2019, 3, 9, 20, 13, 00), '/usr/sbin/syslogd', ),