Unpause and remove breakpoints when detaching from Flutter process with DAP (#101695)
This commit is contained in:
parent
b086473769
commit
675b961573
@ -205,6 +205,9 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
|
||||
/// quickly and therefore may leave orphaned processes.
|
||||
@override
|
||||
Future<void> disconnectImpl() async {
|
||||
if (isAttach) {
|
||||
await preventBreakingAndResume();
|
||||
}
|
||||
terminatePids(ProcessSignal.sigkill);
|
||||
}
|
||||
|
||||
@ -379,6 +382,9 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
|
||||
/// Called by [terminateRequest] to request that we gracefully shut down the app being run (or in the case of an attach, disconnect).
|
||||
@override
|
||||
Future<void> terminateImpl() async {
|
||||
if (isAttach) {
|
||||
await preventBreakingAndResume();
|
||||
}
|
||||
terminatePids(ProcessSignal.sigterm);
|
||||
await _process?.exitCode;
|
||||
}
|
||||
|
@ -380,13 +380,35 @@ void main() {
|
||||
stoppedFuture,
|
||||
dap.client.setBreakpoint(breakpointFilePath, breakpointLine),
|
||||
], eagerError: true);
|
||||
final int threadId = (await stoppedFuture).threadId!;
|
||||
});
|
||||
|
||||
// Remove the breakpoint and resume.
|
||||
await dap.client.clearBreakpoints(breakpointFilePath);
|
||||
await dap.client.continue_(threadId);
|
||||
testWithoutContext('resumes and removes breakpoints on detach', () async {
|
||||
final Uri vmServiceUri = await testProcess.vmServiceUri;
|
||||
|
||||
// Launch the app and wait for it to print "topLevelFunction".
|
||||
await Future.wait(<Future<void>>[
|
||||
dap.client.stdoutOutput.firstWhere((String output) => output.startsWith('topLevelFunction')),
|
||||
dap.client.start(
|
||||
launch: () => dap.client.attach(
|
||||
cwd: project.dir.path,
|
||||
toolArgs: <String>['-d', 'flutter-tester'],
|
||||
vmServiceUri: vmServiceUri.toString(),
|
||||
),
|
||||
),
|
||||
], eagerError: true);
|
||||
|
||||
// Set a breakpoint and expect to hit it.
|
||||
final Future<StoppedEventBody> stoppedFuture = dap.client.stoppedEvents.firstWhere((StoppedEventBody e) => e.reason == 'breakpoint');
|
||||
await Future.wait(<Future<void>>[
|
||||
stoppedFuture,
|
||||
dap.client.setBreakpoint(breakpointFilePath, breakpointLine),
|
||||
], eagerError: true);
|
||||
|
||||
// Detach.
|
||||
await dap.client.terminate();
|
||||
|
||||
// Ensure we get additional output (confirming the process resumed).
|
||||
await testProcess.output.first;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -63,6 +63,11 @@ class SimpleFlutterRunner {
|
||||
unawaited(process.exitCode.then(_handleExitCode));
|
||||
}
|
||||
|
||||
final StreamController<String> _output = StreamController<String>.broadcast();
|
||||
|
||||
/// A broadcast stream of any non-JSON output from the process.
|
||||
Stream<String> get output => _output.stream;
|
||||
|
||||
void _handleExitCode(int code) {
|
||||
if (!_vmServiceUriCompleter.isCompleted) {
|
||||
_vmServiceUriCompleter.completeError('Flutter process ended without producing a VM Service URI');
|
||||
@ -91,8 +96,9 @@ class SimpleFlutterRunner {
|
||||
}
|
||||
}
|
||||
} on FormatException {
|
||||
// `flutter run` writes a lot of text to stdout so just ignore anything
|
||||
// that's not valid JSON.
|
||||
// `flutter run` writes a lot of text to stdout that isn't daemon messages
|
||||
// (not valid JSON), so just pass that one for tests that may want it.
|
||||
_output.add(outputLine);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user