Skip to content

Commit 82bc9ca

Browse files
authored
If one method of finding Dart VM fails for CoreDevice, wait for the other method (#139754)
For CoreDevices we use a combination of mDNS and device logs to find the Dart VM url. If mDNS fails first, it will cause the launch to fail even though the device logs may be able to find the url. So if one of the methods fails, wait for the other method before failing the launch. Fixes flutter/flutter#139685.
1 parent 0c0b77f commit 82bc9ca

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

packages/flutter_tools/lib/src/ios/devices.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,14 @@ class IOSDevice extends Device {
680680
localUri = await Future.any(
681681
<Future<Uri?>>[vmUrlFromMDns, vmUrlFromLogs]
682682
);
683+
684+
// If the first future to return is null, wait for the other to complete.
685+
if (localUri == null) {
686+
final List<Uri?> vmUrls = await Future.wait(
687+
<Future<Uri?>>[vmUrlFromMDns, vmUrlFromLogs]
688+
);
689+
localUri = vmUrls.where((Uri? vmUrl) => vmUrl != null).firstOrNull;
690+
}
683691
} else {
684692
localUri = await vmServiceDiscovery?.uri;
685693
// If the `ios-deploy` debugger loses connection before it finds the

packages/flutter_tools/test/general.shard/ios/ios_device_start_prebuilt_test.dart

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,68 @@ void main() {
904904
}, overrides: <Type, Generator>{
905905
MDnsVmServiceDiscovery: () => FakeMDnsVmServiceDiscovery(),
906906
});
907+
908+
group('IOSDevice.startApp attaches in debug mode via device logging', () {
909+
late FakeMDnsVmServiceDiscovery mdnsDiscovery;
910+
setUp(() {
911+
mdnsDiscovery = FakeMDnsVmServiceDiscovery(returnsNull: true);
912+
});
913+
914+
testUsingContext('when mDNS fails', () async {
915+
final FileSystem fileSystem = MemoryFileSystem.test();
916+
final FakeProcessManager processManager = FakeProcessManager.empty();
917+
918+
final Directory temporaryXcodeProjectDirectory = fileSystem.systemTempDirectory.childDirectory('flutter_empty_xcode.rand0');
919+
final Directory bundleLocation = fileSystem.currentDirectory;
920+
final IOSDevice device = setUpIOSDevice(
921+
processManager: processManager,
922+
fileSystem: fileSystem,
923+
isCoreDevice: true,
924+
coreDeviceControl: FakeIOSCoreDeviceControl(),
925+
xcodeDebug: FakeXcodeDebug(
926+
expectedProject: XcodeDebugProject(
927+
scheme: 'Runner',
928+
xcodeWorkspace: temporaryXcodeProjectDirectory.childDirectory('Runner.xcworkspace'),
929+
xcodeProject: temporaryXcodeProjectDirectory.childDirectory('Runner.xcodeproj'),
930+
hostAppProjectName: 'Runner',
931+
),
932+
expectedDeviceId: '123',
933+
expectedLaunchArguments: <String>['--enable-dart-profiling'],
934+
expectedBundlePath: bundleLocation.path,
935+
)
936+
);
937+
final IOSApp iosApp = PrebuiltIOSApp(
938+
projectBundleId: 'app',
939+
bundleName: 'Runner',
940+
uncompressedBundle: bundleLocation,
941+
applicationPackage: bundleLocation,
942+
);
943+
final FakeDeviceLogReader deviceLogReader = FakeDeviceLogReader();
944+
945+
device.portForwarder = const NoOpDevicePortForwarder();
946+
device.setLogReader(iosApp, deviceLogReader);
947+
948+
unawaited(mdnsDiscovery.completer.future.whenComplete(() {
949+
// Start writing messages to the log reader.
950+
Timer.run(() {
951+
deviceLogReader.addLine('Foo');
952+
deviceLogReader.addLine('The Dart VM service is listening on http://127.0.0.1:456');
953+
});
954+
}));
955+
956+
final LaunchResult launchResult = await device.startApp(iosApp,
957+
prebuiltApplication: true,
958+
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
959+
platformArgs: <String, dynamic>{},
960+
);
961+
962+
expect(launchResult.started, true);
963+
expect(launchResult.hasVmService, true);
964+
expect(await device.stopApp(iosApp), true);
965+
}, overrides: <Type, Generator>{
966+
MDnsVmServiceDiscovery: () => mdnsDiscovery,
967+
});
968+
});
907969
});
908970
});
909971
}
@@ -974,6 +1036,10 @@ class FakeDevicePortForwarder extends Fake implements DevicePortForwarder {
9741036
}
9751037

9761038
class FakeMDnsVmServiceDiscovery extends Fake implements MDnsVmServiceDiscovery {
1039+
FakeMDnsVmServiceDiscovery({this.returnsNull = false});
1040+
bool returnsNull;
1041+
1042+
Completer<void> completer = Completer<void>();
9771043
@override
9781044
Future<Uri?> getVMServiceUriForLaunch(
9791045
String applicationId,
@@ -984,6 +1050,11 @@ class FakeMDnsVmServiceDiscovery extends Fake implements MDnsVmServiceDiscovery
9841050
bool useDeviceIPAsHost = false,
9851051
Duration timeout = Duration.zero,
9861052
}) async {
1053+
completer.complete();
1054+
if (returnsNull) {
1055+
return null;
1056+
}
1057+
9871058
return Uri.tryParse('http://0.0.0.0:1234');
9881059
}
9891060
}

0 commit comments

Comments
 (0)