Fix --pid-file not working for --machine + add to attach command (#23242)
* Fix --pid-file not working for --machine + add to attach
Fixes #23201.
* Add tests for --pid-file in run+attach
diff --git a/packages/flutter_tools/lib/src/base/utils.dart b/packages/flutter_tools/lib/src/base/utils.dart
index a7fe6fa..b9cb836 100644
--- a/packages/flutter_tools/lib/src/base/utils.dart
+++ b/packages/flutter_tools/lib/src/base/utils.dart
@@ -398,6 +398,13 @@
return result.join('\n');
}
+void writePidFile(String pidFile) {
+ if (pidFile != null) {
+ // Write our pid to the file.
+ fs.file(pidFile).writeAsStringSync(io.pid.toString());
+ }
+}
+
// Used to represent a run of ANSI control sequences next to a visible
// character.
class _AnsiRun {
diff --git a/packages/flutter_tools/lib/src/commands/attach.dart b/packages/flutter_tools/lib/src/commands/attach.dart
index 50091d8..0f1b70a 100644
--- a/packages/flutter_tools/lib/src/commands/attach.dart
+++ b/packages/flutter_tools/lib/src/commands/attach.dart
@@ -7,6 +7,7 @@
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
+import '../base/utils.dart';
import '../cache.dart';
import '../commands/daemon.dart';
import '../device.dart';
@@ -44,6 +45,10 @@
..addOption(
'debug-port',
help: 'Local port where the observatory is listening.',
+ )..addOption('pid-file',
+ help: 'Specify a file to write the process id to. '
+ 'You can send SIGUSR1 to trigger a hot reload '
+ 'and SIGUSR2 to trigger a hot restart.',
)..addOption(
'project-root',
hide: !verboseHelp,
@@ -90,6 +95,8 @@
await _validateArguments();
+ writePidFile(argResults['pid-file']);
+
final Device device = await findTargetDevice();
final int devicePort = observatoryPort;
diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart
index b94543e..461c4fc 100644
--- a/packages/flutter_tools/lib/src/commands/run.dart
+++ b/packages/flutter_tools/lib/src/commands/run.dart
@@ -6,7 +6,6 @@
import '../base/common.dart';
import '../base/file_system.dart';
-import '../base/io.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../cache.dart';
@@ -276,6 +275,8 @@
// debug mode.
final bool hotMode = shouldUseHotMode();
+ writePidFile(argResults['pid-file']);
+
if (argResults['machine']) {
if (devices.length > 1)
throwToolExit('--machine does not support -d all.');
@@ -340,12 +341,6 @@
}
}
- final String pidFile = argResults['pid-file'];
- if (pidFile != null) {
- // Write our pid to the file.
- fs.file(pidFile).writeAsStringSync(pid.toString());
- }
-
final List<FlutterDevice> flutterDevices = devices.map<FlutterDevice>((Device device) {
return FlutterDevice(
device,
diff --git a/packages/flutter_tools/test/integration/flutter_attach_test.dart b/packages/flutter_tools/test/integration/flutter_attach_test.dart
index 8b5cff8..2e21ffa 100644
--- a/packages/flutter_tools/test/integration/flutter_attach_test.dart
+++ b/packages/flutter_tools/test/integration/flutter_attach_test.dart
@@ -29,6 +29,15 @@
});
group('attached process', () {
+ test('writes pid-file', () async {
+ final File pidFile = tempDir.childFile('test.pid');
+ await _flutterRun.run(withDebugger: true);
+ await _flutterAttach.attach(
+ _flutterRun.vmServicePort,
+ pidFile: pidFile,
+ );
+ expect(pidFile.existsSync(), isTrue);
+ });
test('can hot reload', () async {
await _flutterRun.run(withDebugger: true);
await _flutterAttach.attach(_flutterRun.vmServicePort);
diff --git a/packages/flutter_tools/test/integration/flutter_run_test.dart b/packages/flutter_tools/test/integration/flutter_run_test.dart
index 2f1a577..fa594cf 100644
--- a/packages/flutter_tools/test/integration/flutter_run_test.dart
+++ b/packages/flutter_tools/test/integration/flutter_run_test.dart
@@ -9,21 +9,25 @@
import '../src/common.dart';
import 'test_data/basic_project.dart';
+import 'test_driver.dart';
import 'test_utils.dart';
void main() {
group('flutter_run', () {
Directory tempDir;
final BasicProject _project = BasicProject();
+ FlutterTestDriver _flutter;
setUp(() async {
tempDir = createResolvedTempDirectorySync();
await _project.setUpIn(tempDir);
+ _flutter = FlutterTestDriver(tempDir);
});
tearDown(() async {
tryToDelete(tempDir);
});
+
test('reports an error if an invalid device is supplied', () async {
// This test forces flutter to check for all possible devices to catch issues
// like https://github.com/flutter/flutter/issues/21418 which were skipped
@@ -44,5 +48,11 @@
fail("'flutter run -d invalid-device-id' did not produce the expected error");
}
});
+
+ test('writes pid-file', () async {
+ final File pidFile = tempDir.childFile('test.pid');
+ await _flutter.run(pidFile: pidFile);
+ expect(pidFile.existsSync(), isTrue);
+ });
}, timeout: const Timeout.factor(6));
}
diff --git a/packages/flutter_tools/test/integration/test_driver.dart b/packages/flutter_tools/test/integration/test_driver.dart
index a6f535e..c7d89c7 100644
--- a/packages/flutter_tools/test/integration/test_driver.dart
+++ b/packages/flutter_tools/test/integration/test_driver.dart
@@ -56,16 +56,25 @@
return msg;
}
- Future<void> run({bool withDebugger = false, bool pauseOnExceptions = false}) async {
+ Future<void> run({
+ bool withDebugger = false,
+ bool pauseOnExceptions = false,
+ File pidFile,
+ }) async {
await _setupProcess(<String>[
'run',
'--machine',
'-d',
'flutter-tester',
- ], withDebugger: withDebugger, pauseOnExceptions: pauseOnExceptions);
+ ], withDebugger: withDebugger, pauseOnExceptions: pauseOnExceptions, pidFile: pidFile);
}
- Future<void> attach(int port, {bool withDebugger = false, bool pauseOnExceptions = false}) async {
+ Future<void> attach(
+ int port, {
+ bool withDebugger = false,
+ bool pauseOnExceptions = false,
+ File pidFile,
+ }) async {
await _setupProcess(<String>[
'attach',
'--machine',
@@ -73,20 +82,28 @@
'flutter-tester',
'--debug-port',
'$port',
- ], withDebugger: withDebugger, pauseOnExceptions: pauseOnExceptions);
+ ], withDebugger: withDebugger, pauseOnExceptions: pauseOnExceptions, pidFile: pidFile);
}
- Future<void> _setupProcess(List<String> args, {bool withDebugger = false, bool pauseOnExceptions = false}) async {
+ Future<void> _setupProcess(
+ List<String> args, {
+ bool withDebugger = false,
+ bool pauseOnExceptions = false,
+ File pidFile,
+ }) async {
final String flutterBin = fs.path.join(getFlutterRoot(), 'bin', 'flutter');
- final List<String> flutterArgs = withDebugger
- ? args.followedBy(<String>['--start-paused']).toList()
- : args;
- _debugPrint('Spawning flutter $flutterArgs in ${_projectFolder.path}');
+ if (withDebugger) {
+ args.add('--start-paused');
+ }
+ if (pidFile != null) {
+ args.addAll(<String>['--pid-file', pidFile.path]);
+ }
+ _debugPrint('Spawning flutter $args in ${_projectFolder.path}');
const ProcessManager _processManager = LocalProcessManager();
_proc = await _processManager.start(
<String>[flutterBin]
- .followedBy(flutterArgs)
+ .followedBy(args)
.toList(),
workingDirectory: _projectFolder.path,
environment: <String, String>{'FLUTTER_TEST': 'true'});