Unverified Commit 5d31b07e authored by Danny Tuppeny's avatar Danny Tuppeny Committed by GitHub

[flutter_tools] [dap] Ensure DAP sends app.stop/app.detach during terminate (#108310)

* [flutter_tools] [dap] Ensure DAP sends app.stop/app.detach during terminate

Fixes an issue where the flutter_tester device may not be cleaned up correctly if we just terminate the Flutter process.

* Update integration test expectations

* Revert accidental commit
parent 925bee92
......@@ -400,6 +400,16 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
if (isAttach) {
await preventBreakingAndResume();
}
// Send a request to stop/detach to give Flutter chance to do some cleanup.
// It's possible the Flutter process will terminate before we process the
// response, so accept either a response or the process exiting.
final String method = isAttach ? 'app.detach' : 'app.stop';
await Future.any<void>(<Future<void>>[
sendFlutterRequest(method, <String, Object?>{'appId': _appId}),
_process?.exitCode ?? Future<void>.value(),
]);
terminatePids(ProcessSignal.sigterm);
await _process?.exitCode;
}
......
......@@ -4,6 +4,7 @@
import 'dart:async';
import 'package:dds/dap.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/cache.dart';
......@@ -96,6 +97,29 @@ void main() {
// Ensure the VM's pid was not recorded.
expect(adapter.pidsToTerminate, isNot(contains(123)));
});
test('calls "app.stop" on terminateRequest', () async {
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
fileSystem: MemoryFileSystem.test(style: fsStyle),
platform: platform,
);
final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
cwd: '/project',
program: 'foo.dart',
);
await adapter.configurationDoneRequest(MockRequest(), null, () {});
final Completer<void> launchCompleter = Completer<void>();
await adapter.launchRequest(MockRequest(), args, launchCompleter.complete);
await launchCompleter.future;
final Completer<void> terminateCompleter = Completer<void>();
await adapter.terminateRequest(MockRequest(), TerminateArguments(restart: false), terminateCompleter.complete);
await terminateCompleter.future;
expect(adapter.flutterRequests, contains('app.stop'));
});
});
group('attachRequest', () {
......@@ -139,6 +163,28 @@ void main() {
// Ensure the VM's pid was not recorded.
expect(adapter.pidsToTerminate, isNot(contains(123)));
});
test('calls "app.detach" on terminateRequest', () async {
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
fileSystem: MemoryFileSystem.test(style: fsStyle),
platform: platform,
);
final FlutterAttachRequestArguments args = FlutterAttachRequestArguments(
cwd: '/project',
);
await adapter.configurationDoneRequest(MockRequest(), null, () {});
final Completer<void> attachCompleter = Completer<void>();
await adapter.attachRequest(MockRequest(), args, attachCompleter.complete);
await attachCompleter.future;
final Completer<void> terminateCompleter = Completer<void>();
await adapter.terminateRequest(MockRequest(), TerminateArguments(restart: false), terminateCompleter.complete);
await terminateCompleter.future;
expect(adapter.flutterRequests, contains('app.detach'));
});
});
group('--start-paused', () {
......
......@@ -43,6 +43,7 @@ class MockFlutterDebugAdapter extends FlutterDebugAdapter {
late String executable;
late List<String> processArgs;
late Map<String, String>? env;
final List<String> flutterRequests = <String>[];
@override
Future<void> launchAsProcess({
......@@ -59,6 +60,16 @@ class MockFlutterDebugAdapter extends FlutterDebugAdapter {
appStartedCompleter.complete();
}
@override
Future<Object?> sendFlutterRequest(
String method,
Map<String, Object?>? params, {
bool failSilently = true,
}) {
flutterRequests.add(method);
return super.sendFlutterRequest(method, params, failSilently: failSilently);
}
@override
Future<void> get debuggerInitialized {
// If we were mocking debug mode, then simulate the debugger initializing.
......
......@@ -64,6 +64,7 @@ void main() {
'Launching $relativeMainPath on Flutter test device in debug mode...',
startsWith('Connecting to VM Service at'),
'topLevelFunction',
'Application finished.',
'',
startsWith('Exited'),
]);
......@@ -94,6 +95,7 @@ void main() {
expectLines(output, <Object>[
'Launching $relativeMainPath on Flutter test device in debug mode...',
'topLevelFunction',
'Application finished.',
'',
startsWith('Exited'),
]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment