Unverified Commit 7f564b74 authored by Zachary Anderson's avatar Zachary Anderson Committed by GitHub

[flutter_tools] Handle StateError in ProtocolDiscovery.uri (#52337)

parent 5d289721
......@@ -629,11 +629,16 @@ class AndroidDevice extends Device {
// TODO(danrubel): Waiting for observatory services can be made common across all devices.
try {
Uri observatoryUri;
if (debuggingOptions.buildInfo.isDebug || debuggingOptions.buildInfo.isProfile) {
observatoryUri = await observatoryDiscovery.uri;
if (observatoryUri == null) {
globals.printError(
'Error waiting for a debug connection: '
'The log reader stopped unexpectedly',
);
return LaunchResult.failed();
}
}
return LaunchResult.succeeded(observatoryUri: observatoryUri);
} on Exception catch (error) {
globals.printError('Error waiting for a debug connection: $error');
......
......@@ -114,14 +114,20 @@ abstract class DesktopDevice extends Device {
);
try {
final Uri observatoryUri = await observatoryDiscovery.uri;
onAttached(package, buildMode, process);
return LaunchResult.succeeded(observatoryUri: observatoryUri);
if (observatoryUri != null) {
onAttached(package, buildMode, process);
return LaunchResult.succeeded(observatoryUri: observatoryUri);
}
globals.printError(
'Error waiting for a debug connection: '
'The log reader stopped unexpectedly.',
);
} on Exception catch (error) {
globals.printError('Error waiting for a debug connection: $error');
return LaunchResult.failed();
} finally {
await observatoryDiscovery.cancel();
}
return LaunchResult.failed();
}
@override
......
......@@ -42,7 +42,8 @@ class FallbackDiscovery {
@required MDnsObservatoryDiscovery mDnsObservatoryDiscovery,
@required Logger logger,
@required ProtocolDiscovery protocolDiscovery,
Future<VmService> Function(String wsUri, {Log log}) vmServiceConnectUri = vm_service_io.vmServiceConnectUri,
Future<VmService> Function(String wsUri, {Log log}) vmServiceConnectUri =
vm_service_io.vmServiceConnectUri,
}) : _logger = logger,
_mDnsObservatoryDiscovery = mDnsObservatoryDiscovery,
_portForwarder = portForwarder,
......@@ -83,19 +84,33 @@ class FallbackDiscovery {
hostVmservicePort: hostVmservicePort,
);
if (result != null) {
UsageEvent(_kEventName, 'mdns-success', flutterUsage: globals.flutterUsage).send();
UsageEvent(
_kEventName,
'mdns-success',
flutterUsage: globals.flutterUsage,
).send();
return result;
}
} on Exception catch (err) {
_logger.printTrace(err.toString());
}
_logger.printTrace('Failed to connect with mDNS, falling back to log scanning');
UsageEvent(_kEventName, 'mdns-failure', flutterUsage: globals.flutterUsage).send();
UsageEvent(
_kEventName,
'mdns-failure',
flutterUsage: globals.flutterUsage,
).send();
try {
final Uri result = await _protocolDiscovery.uri;
UsageEvent(_kEventName, 'fallback-success', flutterUsage: globals.flutterUsage).send();
return result;
if (result != null) {
UsageEvent(
_kEventName,
'fallback-success',
flutterUsage: globals.flutterUsage,
).send();
return result;
}
} on ArgumentError {
// In the event of an invalid InternetAddress, this code attempts to catch
// an ArgumentError from protocol_discovery.dart
......@@ -103,7 +118,11 @@ class FallbackDiscovery {
_logger.printTrace(err.toString());
}
_logger.printTrace('Failed to connect with log scanning');
UsageEvent(_kEventName, 'fallback-failure', flutterUsage: globals.flutterUsage).send();
UsageEvent(
_kEventName,
'fallback-failure',
flutterUsage: globals.flutterUsage,
).send();
return null;
}
......@@ -117,7 +136,10 @@ class FallbackDiscovery {
int hostPort;
Uri assumedWsUri;
try {
hostPort = await _portForwarder.forward(assumedDevicePort, hostPort: hostVmservicePort);
hostPort = await _portForwarder.forward(
assumedDevicePort,
hostPort: hostVmservicePort,
);
assumedWsUri = Uri.parse('ws://localhost:$hostPort/ws');
} on Exception catch (err) {
_logger.printTrace(err.toString());
......@@ -132,17 +154,25 @@ class FallbackDiscovery {
Exception firstException;
while (attempts < 5) {
try {
final VmService vmService = await _vmServiceConnectUri(assumedWsUri.toString());
final VmService vmService = await _vmServiceConnectUri(
assumedWsUri.toString(),
);
final VM vm = await vmService.getVM();
for (final IsolateRef isolateRefs in vm.isolates) {
final dynamic isolateResponse = await vmService.getIsolate(isolateRefs.id);
final dynamic isolateResponse = await vmService.getIsolate(
isolateRefs.id,
);
if (isolateResponse is Sentinel) {
// Might have been a Sentinel. Try again later.
throw Exception('Expected Isolate but found Sentinel: $isolateResponse');
}
final LibraryRef library = (isolateResponse as Isolate).rootLib;
if (library.uri.startsWith('package:$packageName')) {
UsageEvent(_kEventName, 'success', flutterUsage: globals.flutterUsage).send();
UsageEvent(
_kEventName,
'success',
flutterUsage: globals.flutterUsage,
).send();
return Uri.parse('http://localhost:$hostPort');
}
}
......
......@@ -445,13 +445,19 @@ class IOSSimulator extends Device {
try {
final Uri deviceUri = await observatoryDiscovery.uri;
return LaunchResult.succeeded(observatoryUri: deviceUri);
if (deviceUri != null) {
return LaunchResult.succeeded(observatoryUri: deviceUri);
}
globals.printError(
'Error waiting for a debug connection: '
'The log reader failed unexpectedly',
);
} on Exception catch (error) {
globals.printError('Error waiting for a debug connection: $error');
return LaunchResult.failed();
} finally {
await observatoryDiscovery.cancel();
await observatoryDiscovery?.cancel();
}
return LaunchResult.failed();
}
Future<void> _setupUpdatedApplicationBundle(covariant BuildableIOSApp app, BuildInfo buildInfo, String mainPath) async {
......
......@@ -64,10 +64,17 @@ class ProtocolDiscovery {
_BufferedStreamController<Uri> _uriStreamController;
/// The discovered service URL.
///
/// Returns null if the log reader shuts down before any uri is found.
///
/// Use [uris] instead.
// TODO(egarciad): replace `uri` for `uris`.
Future<Uri> get uri {
return uris.first;
Future<Uri> get uri async {
try {
return await uris.first;
} on StateError {
return null;
}
}
/// The discovered service URLs.
......
......@@ -157,6 +157,7 @@ class FlutterTesterDevice extends Device {
command.add(applicationKernelFilePath);
ProtocolDiscovery observatoryDiscovery;
try {
globals.printTrace(command.join(' '));
......@@ -185,7 +186,7 @@ class FlutterTesterDevice extends Device {
return LaunchResult.succeeded();
}
final ProtocolDiscovery observatoryDiscovery = ProtocolDiscovery.observatory(
observatoryDiscovery = ProtocolDiscovery.observatory(
getLogReader(),
hostPort: debuggingOptions.hostVmServicePort,
devicePort: debuggingOptions.deviceVmServicePort,
......@@ -193,11 +194,19 @@ class FlutterTesterDevice extends Device {
);
final Uri observatoryUri = await observatoryDiscovery.uri;
return LaunchResult.succeeded(observatoryUri: observatoryUri);
if (observatoryUri != null) {
return LaunchResult.succeeded(observatoryUri: observatoryUri);
}
globals.printError(
'Failed to launch $package: '
'The log reader failed unexpectedly.',
);
} on Exception catch (error) {
globals.printError('Failed to launch $package: $error');
return LaunchResult.failed();
} finally {
await observatoryDiscovery?.cancel();
}
return LaunchResult.failed();
}
@override
......
......@@ -112,6 +112,14 @@ void main() {
expect(discoverer.uri, throwsA(isFormatException));
});
testUsingContext('uri is null when the log reader closes early', () async {
initialize();
final Future<Uri> uriFuture = discoverer.uri;
await logReader.dispose();
expect(await uriFuture, isNull);
});
testUsingContext('uri waits for correct log line', () async {
initialize();
final Future<Uri> uriFuture = discoverer.uri;
......
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