when setting up the log reader for a device during flutter run
, discard any RPCError
thrown due to the device being disconnected (#155049)
Fixes https://github.com/flutter/flutter/issues/154903 This PR contains some refactoring. To make the actual change easier to figure out, I've tried to separate parts of the change into multiple commits for easier reviewing ð. **I plan on cherry-picking this change to stable.**
This commit is contained in:
parent
50a190caec
commit
d8f8613a5b
@ -416,8 +416,19 @@ class FlutterDevice {
|
||||
_loggingSubscription = null;
|
||||
}
|
||||
|
||||
Future<void> initLogReader() async {
|
||||
final vm_service.VM vm = await vmService!.service.getVM();
|
||||
/// Attempts to set up reading logs from the Flutter app on the device.
|
||||
///
|
||||
/// This can fail if the device if no longer connected.
|
||||
Future<void> tryInitLogReader() async {
|
||||
final vm_service.VM? vm = await vmService!.getVmGuarded();
|
||||
if (vm == null) {
|
||||
globals.printError(
|
||||
'Unable to initiate log reader for device'
|
||||
'${device?.name}, because the Flutter VM service connection '
|
||||
'is closed.',
|
||||
);
|
||||
return;
|
||||
}
|
||||
final DeviceLogReader logReader = await device!.getLogReader(app: package);
|
||||
logReader.appPid = vm.pid;
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ class ColdRunner extends ResidentRunner {
|
||||
if (device!.vmService == null) {
|
||||
continue;
|
||||
}
|
||||
await device.initLogReader();
|
||||
await device.tryInitLogReader();
|
||||
globals.printTrace('Connected to ${device.device!.name}');
|
||||
}
|
||||
|
||||
@ -154,7 +154,7 @@ class ColdRunner extends ResidentRunner {
|
||||
}
|
||||
|
||||
for (final FlutterDevice? device in flutterDevices) {
|
||||
await device!.initLogReader();
|
||||
await device!.tryInitLogReader();
|
||||
}
|
||||
for (final FlutterDevice? device in flutterDevices) {
|
||||
final List<FlutterView> views = await device!.vmService!.getFlutterViews();
|
||||
|
@ -261,7 +261,7 @@ class HotRunner extends ResidentRunner {
|
||||
}
|
||||
|
||||
for (final FlutterDevice? device in flutterDevices) {
|
||||
await device!.initLogReader();
|
||||
await device!.tryInitLogReader();
|
||||
device
|
||||
.developmentShaderCompiler
|
||||
.configureCompiler(device.targetPlatform);
|
||||
|
@ -491,6 +491,22 @@ class FlutterVmService {
|
||||
final Uri? wsAddress;
|
||||
final Uri? httpAddress;
|
||||
|
||||
/// Calls [service.getVM]. However, in the case that an [vm_service.RPCError]
|
||||
/// is thrown due to the service being disconnected, the error is discarded
|
||||
/// and null is returned.
|
||||
Future<vm_service.VM?> getVmGuarded() async {
|
||||
try {
|
||||
return await service.getVM();
|
||||
} on vm_service.RPCError catch (err) {
|
||||
if (err.code == RPCErrorCodes.kServiceDisappeared ||
|
||||
err.message.contains('Service connection disposed')) {
|
||||
globals.printTrace('VmService.getVm call failed: $err');
|
||||
return null;
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<vm_service.Response?> callMethodWrapper(
|
||||
String method, {
|
||||
String? isolateId,
|
||||
|
@ -165,7 +165,7 @@ class FakeFlutterDevice extends Fake implements FlutterDevice {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> initLogReader() async { }
|
||||
Future<void> tryInitLogReader() async { }
|
||||
}
|
||||
|
||||
class FakeDevice extends Fake implements Device {
|
||||
|
@ -228,7 +228,7 @@ class FakeFlutterDevice extends Fake implements FlutterDevice {
|
||||
Future<void> stopEchoingDeviceLog() async { }
|
||||
|
||||
@override
|
||||
Future<void> initLogReader() async { }
|
||||
Future<void> tryInitLogReader() async { }
|
||||
|
||||
@override
|
||||
Future<Uri> setupDevFS(String fsName, Directory rootDirectory) async {
|
||||
|
@ -1934,6 +1934,43 @@ flutter:
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testUsingContext('FlutterDevice does not throw when unable to initiate log reader due to VM service disconnection', () async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(
|
||||
requests: <VmServiceExpectation>[
|
||||
const FakeVmServiceRequest(
|
||||
method: 'getVM',
|
||||
error: FakeRPCError(
|
||||
code: RPCErrorCodes.kServerError,
|
||||
error: 'Service connection disposed',
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
final TestFlutterDevice flutterDevice = TestFlutterDevice(device);
|
||||
flutterDevice.vmService = fakeVmServiceHost!.vmService;
|
||||
await flutterDevice.tryInitLogReader();
|
||||
final BufferLogger logger = globals.logger as BufferLogger;
|
||||
expect(
|
||||
logger.traceText,
|
||||
contains(
|
||||
'VmService.getVm call failed: getVM: (-32000) '
|
||||
'Service connection disposed\n',
|
||||
),
|
||||
);
|
||||
expect(
|
||||
logger.errorText,
|
||||
contains(
|
||||
'Unable to initiate log reader for deviceFakeDevice, because '
|
||||
'the Flutter VM service connection is closed.\n',
|
||||
),
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
Logger: () => BufferLogger.test(),
|
||||
Artifacts: () => Artifacts.test(),
|
||||
FileSystem: () => MemoryFileSystem.test(),
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testUsingContext('Uses existing DDS URI from exception field', () => testbed.run(() async {
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
final FakeDevice device = FakeDevice()
|
||||
|
@ -1755,7 +1755,7 @@ class FakeFlutterDevice extends Fake implements FlutterDevice {
|
||||
Future<void> stopEchoingDeviceLog() async {}
|
||||
|
||||
@override
|
||||
Future<void> initLogReader() async {}
|
||||
Future<void> tryInitLogReader() async {}
|
||||
|
||||
@override
|
||||
Future<Uri?> setupDevFS(String fsName, Directory rootDirectory) async {
|
||||
|
Loading…
x
Reference in New Issue
Block a user