diff --git a/dev/benchmarks/macrobenchmarks/pubspec.yaml b/dev/benchmarks/macrobenchmarks/pubspec.yaml index 198cd29f14..d53532ab3e 100644 --- a/dev/benchmarks/macrobenchmarks/pubspec.yaml +++ b/dev/benchmarks/macrobenchmarks/pubspec.yaml @@ -55,7 +55,6 @@ dependencies: path_provider_windows: 0.0.4+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" pedantic: 1.10.0-nullsafety.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" platform: 3.0.0-nullsafety.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - platform_detect: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" plugin_platform_interface: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" process: 4.0.0-nullsafety.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" pub_semver: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -75,11 +74,11 @@ dependencies: sync_http: 0.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" term_glyph: 1.2.0-nullsafety.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - url_launcher: 5.7.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + url_launcher: 5.7.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" url_launcher_linux: 0.0.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" url_launcher_macos: 0.0.1+8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" url_launcher_platform_interface: 1.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - url_launcher_web: 0.1.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + url_launcher_web: 0.1.4+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" url_launcher_windows: 0.0.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vm_service_client: 0.2.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -299,4 +298,4 @@ flutter: fonts: - asset: packages/flutter_gallery_assets/fonts/GalleryIcons.ttf -# PUBSPEC CHECKSUM: c0a7 +# PUBSPEC CHECKSUM: 6419 diff --git a/dev/bots/pubspec.yaml b/dev/bots/pubspec.yaml index ef296c630d..1a1bc39cb5 100644 --- a/dev/bots/pubspec.yaml +++ b/dev/bots/pubspec.yaml @@ -36,7 +36,7 @@ dependencies: glob: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" html: 0.14.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" http_multi_server: 2.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - image: 2.1.17 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + image: 2.1.18 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" io: 0.3.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" js: 0.6.3-nullsafety.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" json_rpc_2: 2.2.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -76,4 +76,4 @@ dev_dependencies: mockito: 4.1.1 test_api: 0.2.19-nullsafety.2 -# PUBSPEC CHECKSUM: 646a +# PUBSPEC CHECKSUM: e26b diff --git a/dev/devicelab/pubspec.yaml b/dev/devicelab/pubspec.yaml index 5e24d088ba..f93f080d45 100644 --- a/dev/devicelab/pubspec.yaml +++ b/dev/devicelab/pubspec.yaml @@ -10,7 +10,7 @@ environment: dependencies: args: 1.6.0 file: 6.0.0-nullsafety.2 - image: 2.1.17 + image: 2.1.18 meta: 1.3.0-nullsafety.3 path: 1.8.0-nullsafety.1 platform: 3.0.0-nullsafety.2 @@ -75,4 +75,4 @@ dev_dependencies: webkit_inspection_protocol: 0.7.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: d925 +# PUBSPEC CHECKSUM: 3c26 diff --git a/dev/integration_tests/flutter_gallery/pubspec.yaml b/dev/integration_tests/flutter_gallery/pubspec.yaml index 4323868d78..1e7e555d7c 100644 --- a/dev/integration_tests/flutter_gallery/pubspec.yaml +++ b/dev/integration_tests/flutter_gallery/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: intl: 0.16.1 connectivity: 0.4.9+3 string_scanner: 1.1.0-nullsafety.1 - url_launcher: 5.7.1 + url_launcher: 5.7.2 cupertino_icons: 0.1.3 video_player: 0.10.6 scoped_model: 1.0.1 @@ -30,16 +30,14 @@ dependencies: device_info_platform_interface: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" meta: 1.3.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" path: 1.8.0-nullsafety.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - platform_detect: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" plugin_platform_interface: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - pub_semver: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" source_span: 1.8.0-nullsafety.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" term_glyph: 1.2.0-nullsafety.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" url_launcher_linux: 0.0.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" url_launcher_macos: 0.0.1+8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" url_launcher_platform_interface: 1.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - url_launcher_web: 0.1.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + url_launcher_web: 0.1.4+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" url_launcher_windows: 0.0.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.0-nullsafety.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" video_player_platform_interface: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -88,6 +86,7 @@ dev_dependencies: platform: 3.0.0-nullsafety.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" pool: 1.5.0-nullsafety.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" process: 4.0.0-nullsafety.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + pub_semver: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" shelf: 0.7.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" shelf_packages_handler: 2.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -278,4 +277,4 @@ flutter: - asset: packages/flutter_gallery_assets/fonts/merriweather/Merriweather-Regular.ttf - asset: packages/flutter_gallery_assets/fonts/merriweather/Merriweather-Light.ttf -# PUBSPEC CHECKSUM: 1166 +# PUBSPEC CHECKSUM: 5ed7 diff --git a/dev/integration_tests/ui/pubspec.yaml b/dev/integration_tests/ui/pubspec.yaml index 894ba7a3c7..c069624505 100644 --- a/dev/integration_tests/ui/pubspec.yaml +++ b/dev/integration_tests/ui/pubspec.yaml @@ -6,7 +6,7 @@ environment: sdk: ">=2.8.0 <3.0.0" dependencies: - image: 2.1.17 + image: 2.1.18 flutter: sdk: flutter flutter_driver: @@ -84,4 +84,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: b22c +# PUBSPEC CHECKSUM: 252d diff --git a/packages/flutter_tools/lib/src/base/dds.dart b/packages/flutter_tools/lib/src/base/dds.dart index 7da8667b03..6eaaf20215 100644 --- a/packages/flutter_tools/lib/src/base/dds.dart +++ b/packages/flutter_tools/lib/src/base/dds.dart @@ -2,9 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:async'; + import 'package:dds/dds.dart' as dds; import 'package:meta/meta.dart'; +import 'common.dart'; import 'io.dart' as io; import 'logger.dart'; @@ -18,6 +21,9 @@ class DartDevelopmentService { Uri get uri => _ddsInstance.uri; + Future get done => _completer.future; + final Completer _completer = Completer(); + Future startDartDevelopmentService( Uri observatoryUri, int hostPort, @@ -43,9 +49,11 @@ class DartDevelopmentService { enableAuthCodes: !disableServiceAuthCodes, ipv6: ipv6, ); + unawaited(_ddsInstance.done.whenComplete(_completer.complete)); logger.printTrace('DDS is listening at ${_ddsInstance.uri}.'); } on dds.DartDevelopmentServiceException catch (e) { - logger.printError('Warning: Failed to start DDS: ${e.message}'); + logger.printTrace('Warning: Failed to start DDS: ${e.message}'); + _completer.complete(); rethrow; } } diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index d738a1c928..aa3c422f70 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart @@ -230,24 +230,44 @@ class FlutterDevice { isWaitingForVm = true; vm_service.VmService service; if (!disableDds) { - await device.dds.startDartDevelopmentService( - observatoryUri, - ddsPort, - ipv6, - disableServiceAuthCodes, - ); + // This first try block is meant to catch errors that occur during DDS startup + // (e.g., failure to bind to a port, failure to connect to the VM service, + // attaching to a VM service with existing clients, etc.). + try { + await device.dds.startDartDevelopmentService( + observatoryUri, + ddsPort, + ipv6, + disableServiceAuthCodes, + ); + } on Exception catch (e) { + globals.printTrace('Fail to connect to service protocol: $observatoryUri: $e'); + if (!completer.isCompleted && !_isListeningForObservatoryUri) { + completer.completeError('failed to connect to $observatoryUri'); + } + return; + } } + // This second try block handles cases where the VM service connection goes down + // before flutter_tools connects to DDS. The DDS `done` future completes when DDS + // shuts down, including after an error. If `done` completes before `connectToVmService`, + // something went wrong that caused DDS to shutdown early. try { - service = await connectToVmService( - disableDds ? observatoryUri : device.dds.uri, - reloadSources: reloadSources, - restart: restart, - compileExpression: compileExpression, - reloadMethod: reloadMethod, - getSkSLMethod: getSkSLMethod, - printStructuredErrorLogMethod: printStructuredErrorLogMethod, - device: device, - ); + service = await Future.any( + >[ + connectToVmService( + disableDds ? observatoryUri : device.dds.uri, + reloadSources: reloadSources, + restart: restart, + compileExpression: compileExpression, + reloadMethod: reloadMethod, + getSkSLMethod: getSkSLMethod, + printStructuredErrorLogMethod: printStructuredErrorLogMethod, + device: device, + ), + device.dds.done.whenComplete(() => throw Exception('DDS shut down too early')), + ] + ) as vm_service.VmService; } on Exception catch (exception) { globals.printTrace('Fail to connect to service protocol: $observatoryUri: $exception'); if (!completer.isCompleted && !_isListeningForObservatoryUri) { diff --git a/packages/flutter_tools/pubspec.yaml b/packages/flutter_tools/pubspec.yaml index 843fc242ce..d0a9c454e1 100644 --- a/packages/flutter_tools/pubspec.yaml +++ b/packages/flutter_tools/pubspec.yaml @@ -11,7 +11,7 @@ dependencies: # To update these, use "flutter update-packages --force-upgrade". archive: 2.0.13 args: 1.6.0 - dds: 1.3.5 + dds: 1.4.0 dwds: 6.0.0 completion: 0.2.2 coverage: 0.14.1 @@ -113,4 +113,4 @@ dartdoc: # Exclude this package from the hosted API docs. nodoc: true -# PUBSPEC CHECKSUM: 8b89 +# PUBSPEC CHECKSUM: 3d85 diff --git a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart index 116b48f9fe..41a07b07d7 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart @@ -90,8 +90,10 @@ void main() { when(portForwarder.unforward(any)) .thenAnswer((_) async {}); when(device.dds).thenReturn(mockDds); + final Completer noopCompleter = Completer(); when(mockDds.startDartDevelopmentService(any, any, false, any)).thenReturn(null); when(mockDds.uri).thenReturn(Uri.parse('http://localhost:8181')); + when(mockDds.done).thenAnswer((_) => noopCompleter.future); final HttpClientRequest httpClientRequest = MockHttpClientRequest(); httpClient = MockHttpClient(); when(httpClient.putUrl(any)) @@ -299,6 +301,8 @@ void main() { .thenReturn(portForwarder); when(device.dds) .thenReturn(mockDds); + final Completer noopCompleter = Completer(); + when(mockDds.done).thenAnswer((_) => noopCompleter.future); when(portForwarder.forward(devicePort, hostPort: anyNamed('hostPort'))) .thenAnswer((_) async => hostPort); when(portForwarder.forwardedPorts) @@ -379,6 +383,8 @@ void main() { .thenReturn(portForwarder); when(device.dds) .thenReturn(mockDds); + final Completer noopCompleter = Completer(); + when(mockDds.done).thenAnswer((_) => noopCompleter.future); when(device.getLogReader(includePastLogs: anyNamed('includePastLogs'))) .thenAnswer((_) => mockLogReader); when(portForwarder.forward(devicePort, hostPort: anyNamed('hostPort'))) @@ -449,6 +455,8 @@ void main() { when(mockDds.startDartDevelopmentService(any, any, any, any)) .thenReturn(null); when(mockDds.uri).thenReturn(Uri.parse('http://localhost:8181')); + final Completer noopCompleter = Completer(); + when(mockDds.done).thenAnswer((_) => noopCompleter.future); }); testUsingContext('succeeds in ipv4 mode', () async { diff --git a/packages/flutter_tools/test/general.shard/resident_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_runner_test.dart index 2813c47998..c559165b43 100644 --- a/packages/flutter_tools/test/general.shard/resident_runner_test.dart +++ b/packages/flutter_tools/test/general.shard/resident_runner_test.dart @@ -2328,10 +2328,12 @@ void main() { final MockDevice mockDevice = MockDevice(); final MockDartDevelopmentService mockDds = MockDartDevelopmentService(); final MockDeviceLogReader mockLogReader = MockDeviceLogReader(); + final Completer noopCompleter = Completer(); when(mockDevice.getLogReader(app: anyNamed('app'))).thenReturn(mockLogReader); when(mockDevice.dds).thenReturn(mockDds); when(mockDds.startDartDevelopmentService(any, any, any, any)).thenReturn(null); when(mockDds.uri).thenReturn(Uri.parse('http://localhost:8181')); + when(mockDds.done).thenAnswer((_) => noopCompleter.future); final TestFlutterDevice flutterDevice = TestFlutterDevice( mockDevice, diff --git a/packages/flutter_tools/test/integration.shard/flutter_immediately_exit_test.dart b/packages/flutter_tools/test/integration.shard/flutter_immediately_exit_test.dart new file mode 100644 index 0000000000..c90059abac --- /dev/null +++ b/packages/flutter_tools/test/integration.shard/flutter_immediately_exit_test.dart @@ -0,0 +1,43 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file/file.dart'; + +import '../src/common.dart'; +import 'test_data/project_with_immediate_exit.dart'; +import 'test_driver.dart'; +import 'test_utils.dart'; + +void main() { + Directory tempDir; + final ProjectWithImmediateExit _project = ProjectWithImmediateExit(); + FlutterRunTestDriver _flutter; + + setUp(() async { + tempDir = createResolvedTempDirectorySync('run_test.'); + await _project.setUpIn(tempDir); + _flutter = FlutterRunTestDriver(tempDir); + }); + + tearDown(() async { + tryToDelete(tempDir); + }); + + + testWithoutContext('flutter_tools gracefully handles quick app shutdown', () async { + try { + await _flutter.run(); + } on Exception { + expect(_flutter.lastErrorInfo, contains('Error connecting to the service protocol:')); + expect( + _flutter.lastErrorInfo.contains( + // Looks for stack trace entry of the form: + // test/integration.shard/test_driver.dart 379:18 FlutterTestDriver._waitFor. + RegExp('^(.+)\/([^\/]+)\.dart \d*:\d*\s*.*\$') + ), + isFalse + ); + } + }); +} diff --git a/packages/flutter_tools/test/integration.shard/test_data/project_with_immediate_exit.dart b/packages/flutter_tools/test/integration.shard/test_data/project_with_immediate_exit.dart new file mode 100644 index 0000000000..4a7a946df1 --- /dev/null +++ b/packages/flutter_tools/test/integration.shard/test_data/project_with_immediate_exit.dart @@ -0,0 +1,31 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'project.dart'; + +class ProjectWithImmediateExit extends Project { + + @override + final String pubspec = ''' + name: test + environment: + sdk: ">=2.0.0-dev.68.0 <3.0.0" + + dependencies: + flutter: + sdk: flutter + '''; + + @override + final String main = r''' + import 'dart:async'; + import 'dart:io'; + + Future main() async { + await Future.delayed(const Duration(milliseconds: 50)); + exit(0); + } + '''; + +} diff --git a/packages/flutter_tools/test/integration.shard/test_driver.dart b/packages/flutter_tools/test/integration.shard/test_driver.dart index 36f98effdd..afa33309dc 100644 --- a/packages/flutter_tools/test/integration.shard/test_driver.dart +++ b/packages/flutter_tools/test/integration.shard/test_driver.dart @@ -376,7 +376,7 @@ abstract class FlutterTestDriver { if (json['params'] != null && json['params']['trace'] != null) { error.write('${json['params']['trace']}\n\n'); } - response.completeError(error.toString()); + response.completeError(Exception(error.toString())); } }); @@ -536,7 +536,7 @@ class FlutterRunTestDriver extends FlutterTestDriver { // fast. unawaited(_process.exitCode.then((_) { if (!prematureExitGuard.isCompleted) { - prematureExitGuard.completeError('Process exited prematurely: ${args.join(' ')}: $_errorBuffer'); + prematureExitGuard.completeError(Exception('Process exited prematurely: ${args.join(' ')}: $_errorBuffer')); } })); @@ -567,7 +567,7 @@ class FlutterRunTestDriver extends FlutterTestDriver { _currentRunningAppId = (await started)['params']['appId'] as String; prematureExitGuard.complete(); } on Exception catch (error, stackTrace) { - prematureExitGuard.completeError(error, stackTrace); + prematureExitGuard.completeError(Exception(error.toString()), stackTrace); } }());