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;
|
_loggingSubscription = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> initLogReader() async {
|
/// Attempts to set up reading logs from the Flutter app on the device.
|
||||||
final vm_service.VM vm = await vmService!.service.getVM();
|
///
|
||||||
|
/// 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);
|
final DeviceLogReader logReader = await device!.getLogReader(app: package);
|
||||||
logReader.appPid = vm.pid;
|
logReader.appPid = vm.pid;
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ class ColdRunner extends ResidentRunner {
|
|||||||
if (device!.vmService == null) {
|
if (device!.vmService == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
await device.initLogReader();
|
await device.tryInitLogReader();
|
||||||
globals.printTrace('Connected to ${device.device!.name}');
|
globals.printTrace('Connected to ${device.device!.name}');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ class ColdRunner extends ResidentRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final FlutterDevice? device in flutterDevices) {
|
for (final FlutterDevice? device in flutterDevices) {
|
||||||
await device!.initLogReader();
|
await device!.tryInitLogReader();
|
||||||
}
|
}
|
||||||
for (final FlutterDevice? device in flutterDevices) {
|
for (final FlutterDevice? device in flutterDevices) {
|
||||||
final List<FlutterView> views = await device!.vmService!.getFlutterViews();
|
final List<FlutterView> views = await device!.vmService!.getFlutterViews();
|
||||||
|
@ -261,7 +261,7 @@ class HotRunner extends ResidentRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final FlutterDevice? device in flutterDevices) {
|
for (final FlutterDevice? device in flutterDevices) {
|
||||||
await device!.initLogReader();
|
await device!.tryInitLogReader();
|
||||||
device
|
device
|
||||||
.developmentShaderCompiler
|
.developmentShaderCompiler
|
||||||
.configureCompiler(device.targetPlatform);
|
.configureCompiler(device.targetPlatform);
|
||||||
|
@ -491,6 +491,22 @@ class FlutterVmService {
|
|||||||
final Uri? wsAddress;
|
final Uri? wsAddress;
|
||||||
final Uri? httpAddress;
|
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(
|
Future<vm_service.Response?> callMethodWrapper(
|
||||||
String method, {
|
String method, {
|
||||||
String? isolateId,
|
String? isolateId,
|
||||||
|
@ -165,7 +165,7 @@ class FakeFlutterDevice extends Fake implements FlutterDevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> initLogReader() async { }
|
Future<void> tryInitLogReader() async { }
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeDevice extends Fake implements Device {
|
class FakeDevice extends Fake implements Device {
|
||||||
|
@ -228,7 +228,7 @@ class FakeFlutterDevice extends Fake implements FlutterDevice {
|
|||||||
Future<void> stopEchoingDeviceLog() async { }
|
Future<void> stopEchoingDeviceLog() async { }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> initLogReader() async { }
|
Future<void> tryInitLogReader() async { }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Uri> setupDevFS(String fsName, Directory rootDirectory) async {
|
Future<Uri> setupDevFS(String fsName, Directory rootDirectory) async {
|
||||||
|
@ -1934,6 +1934,43 @@ flutter:
|
|||||||
ProcessManager: () => FakeProcessManager.any(),
|
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 {
|
testUsingContext('Uses existing DDS URI from exception field', () => testbed.run(() async {
|
||||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||||
final FakeDevice device = FakeDevice()
|
final FakeDevice device = FakeDevice()
|
||||||
|
@ -1755,7 +1755,7 @@ class FakeFlutterDevice extends Fake implements FlutterDevice {
|
|||||||
Future<void> stopEchoingDeviceLog() async {}
|
Future<void> stopEchoingDeviceLog() async {}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> initLogReader() async {}
|
Future<void> tryInitLogReader() async {}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Uri?> setupDevFS(String fsName, Directory rootDirectory) async {
|
Future<Uri?> setupDevFS(String fsName, Directory rootDirectory) async {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user