Skip to content

Properly await Dart Development Service shutdown with timeout#188387

Merged
auto-submit[bot] merged 3 commits into
flutter:masterfrom
bkonyi:reproduce-dds-exit-issue
Jun 29, 2026
Merged

Properly await Dart Development Service shutdown with timeout#188387
auto-submit[bot] merged 3 commits into
flutter:masterfrom
bkonyi:reproduce-dds-exit-issue

Conversation

@bkonyi

@bkonyi bkonyi commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

This PR addresses the issue where flutter test (specifically integration tests) hangs at teardown on CPU-starved CI runners because the Dart Development Service (DDS) fails to exit cleanly.

Changes

  • Modify DartDevelopmentService.shutdown to return Future<void> and properly await the underlying DDS instance shutdown.
  • Update IntegrationTestTestDevice.kill to await the DDS shutdown with a configurable timeout (defaulting to 5 seconds, using ddsShutdownTimeout), preventing permanent hangs if DDS fails to exit.
  • Update ResidentRunner.shutdownDartDevelopmentService to also be asynchronous and await all DDS shutdowns with a 10-second safety timeout to prevent flutter run from hanging on exit.
  • Propagate the async shutdown signature to all callers and mock implementations in tests.
  • Add a regression test in integration_test_device_test.dart to verify that kill() completes even if DDS shutdown hangs (times out).

Verification

  • Ran static analysis (dart analyze) on the entire packages/flutter_tools package with zero issues.
  • Ran all unit tests in integration_test_device_test.dart and they passed (including the new regression test).
  • Verified that integration tests on Linux desktop run and exit cleanly.

Fixes #187984

Modify `DartDevelopmentService.shutdown` to return `Future<void>` and properly await the underlying DDS instance shutdown.

Update `IntegrationTestTestDevice.kill` to await the DDS shutdown with a configurable timeout (defaulting to 5 seconds), preventing permanent hangs on CPU-starved CI runners if DDS fails to exit.

Update `ResidentRunner.shutdownDartDevelopmentService` to also be asynchronous and await all DDS shutdowns with a 10-second safety timeout to prevent `flutter run` from hanging on exit.

Propagate the async `shutdown` signature to all callers and mock implementations in tests.
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jun 23, 2026
@github-actions github-actions Bot added the tool Affects the "flutter" command-line tool. See also t: labels. label Jun 23, 2026
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 23, 2026
@bkonyi bkonyi added the CICD Run CI/CD label Jun 23, 2026
@bkonyi
bkonyi marked this pull request as ready for review June 25, 2026 20:58
@bkonyi
bkonyi requested a review from chingjun June 25, 2026 20:58

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the Dart Development Service (DDS) shutdown process to be asynchronous, updating the shutdown method to return a Future and ensuring callers await its completion. It also introduces shutdown timeouts in ResidentRunner and IntegrationTestTestDevice. The review feedback suggests improving error handling by catching all exceptions during shutdown in IntegrationTestTestDevice to prevent potential hangs, and wrapping individual device shutdowns in ResidentRunner to ensure a single failure does not abort the entire shutdown process.

Comment on lines +157 to +161
try {
await _ddsLauncher.shutdown().timeout(ddsShutdownTimeout);
} on TimeoutException {
globals.printTrace('Warning: Dart Development Service shutdown timed out.');
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If _ddsLauncher.shutdown() throws any exception other than TimeoutException (such as a StateError or network-related exception), the exception will propagate and prevent _finished.complete() from being called. This can cause the test runner to hang or leak resources during teardown.\n\nWe should catch all exceptions during the shutdown attempt to ensure _finished.complete() is always executed.

    try {\n      await _ddsLauncher.shutdown().timeout(ddsShutdownTimeout);\n    } on TimeoutException {\n      globals.printTrace('Warning: Dart Development Service shutdown timed out.');\n    } catch (error) {\n      globals.printTrace('Warning: Failed to shut down Dart Development Service: $error');\n    }

Comment on lines +1203 to 1214
try {
await Future.wait<void>(
flutterDevices.map<Future<void>>((FlutterDevice device) async {
final DartDevelopmentService? dds = device.device?.dds;
if (dds != null) {
await dds.shutdown();
}
}),
).timeout(const Duration(seconds: 10));
} on TimeoutException {
globals.printTrace('Warning: shutdownDartDevelopmentService timed out.');
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If any of the dds.shutdown() calls throw an exception other than TimeoutException, the exception will propagate out of Future.wait immediately. This prevents other DDS instances in the list from completing their shutdown, and can interrupt the runner's teardown/cleanup flow.\n\nWe should wrap each individual dds.shutdown() call in a try-catch block to ensure that a failure in one DDS instance does not affect others or abort the entire shutdown process.

    try {\n      await Future.wait<void>(\n        flutterDevices.map<Future<void>>((FlutterDevice device) async {\n          final DartDevelopmentService? dds = device.device?.dds;\n          if (dds != null) {\n            try {\n              await dds.shutdown();\n            } catch (error) {\n              globals.printTrace('Warning: Failed to shut down DDS for device: $error');\n            }\n          }\n        }),\n      ).timeout(const Duration(seconds: 10));\n    } on TimeoutException {\n      globals.printTrace('Warning: shutdownDartDevelopmentService timed out.');\n    }

- Catch all exceptions during DDS shutdown in IntegrationTestTestDevice to ensure teardown completes.
- Wrap individual device DDS shutdowns in ResidentRunner to prevent a single failure from aborting the entire teardown flow.
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 25, 2026
@bkonyi bkonyi added the CICD Run CI/CD label Jun 25, 2026
@bkonyi bkonyi added the autosubmit Merge PR when tree becomes green via auto submit App label Jun 29, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Jun 29, 2026
Merged via the queue into flutter:master with commit e08edd0 Jun 29, 2026
168 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jun 29, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Jul 7, 2026
…#12081)

Manual roll Flutter from 0c80830e465b to ca9f874f5284 (119 revisions)

Manual roll requested by [email protected]

flutter/flutter@0c80830...ca9f874

2026-06-30 [email protected] [tool] Don't require a Flutter compile task when staging jniLibs (flutter/flutter#188805)
2026-06-30 [email protected] [Impeller] Fix potential overflow when allocating buffers at the next power of two size (flutter/flutter#188742)
2026-06-30 [email protected] [Framework/Tool] Decouple preview theme imports (flutter/flutter#188176)
2026-06-30 [email protected] Add import of `dart:_js_interop_wasm` in sdk rewriter tool (flutter/flutter#188620)
2026-06-30 [email protected] Detach LLDB and print stack trace on process stop (flutter/flutter#188576)
2026-06-30 [email protected] [Linux] Fix FlCompositorOpenGL.pixels comment (flutter/flutter#188754)
2026-06-30 [email protected] [flutter_tools] Fix crash in flutter create when pubspec.yaml is empty (flutter/flutter#188385)
2026-06-30 [email protected] Roll Packages from 656ccaa to 274ed3e (23 revisions) (flutter/flutter#188792)
2026-06-30 [email protected] In AndroidImageGenerator, check that the destination pixel buffer has sufficient capacity for the decoded data (flutter/flutter#188752)
2026-06-30 [email protected] Roll pub packages (flutter/flutter#188773)
2026-06-30 [email protected] [Impeller] Add a flat VertexAttributeFormat for vertex inputs (flutter/flutter#188684)
2026-06-30 [email protected] Roll pub packages (flutter/flutter#188764)
2026-06-30 [email protected] Roll Dart SDK from 0cb483880b6b to e1bdb9ce3327 (2 revisions) (flutter/flutter#188763)
2026-06-29 [email protected] Handle 'no permissions' adb device state (flutter/flutter#187248)
2026-06-29 [email protected] [windows]: adjusts uniform buffers to hit hlsl optimization (flutter/flutter#188538)
2026-06-29 [email protected] Roll Skia from bfb7860cb9c7 to 71947c4110b0 (9 revisions) (flutter/flutter#188747)
2026-06-29 [email protected] ci: extract wait-for-engine-build logic into a reusable composite action (flutter/flutter#188748)
2026-06-29 [email protected] Provide guided migration logs when iOS app crashes on simulator (flutter/flutter#188736)
2026-06-29 [email protected] Revert "[flutter_tools] Track asset transformer dependencies for hot reload" (flutter/flutter#188751)
2026-06-29 [email protected] Migrate ABI splits to new AGP dsl (flutter/flutter#188369)
2026-06-29 [email protected] Add Impeller+OpenGLES startup benchmark for mokey (flutter/flutter#188495)
2026-06-29 [email protected] Increase macOS minimum supported version from 10.15 to 12 to support Xcode 27  (flutter/flutter#188520)
2026-06-29 [email protected] Moves test ownership validation to flutter/flutter (flutter/flutter#188655)
2026-06-29 [email protected] Add --flavor support for Windows desktop builds (flutter/flutter#187034)
2026-06-29 [email protected] Android_hardware_smoke_test: Enable pixel exact local file comparator to read goldens from flutter asset URI (flutter/flutter#188587)
2026-06-29 [email protected] [flutter_tools] Use DeviceHub.app for iOS simulator path on Xcode 27+ (flutter/flutter#187910)
2026-06-29 [email protected] Roll Skia from 111e7582d081 to bfb7860cb9c7 (2 revisions) (flutter/flutter#188731)
2026-06-29 [email protected] Use `revert` label instead of `revert_wf` (flutter/flutter#188639)
2026-06-29 [email protected] Properly await Dart Development Service shutdown with timeout (flutter/flutter#188387)
2026-06-29 [email protected] [flutter_tools] Track asset transformer dependencies for hot reload (flutter/flutter#187947)
2026-06-29 [email protected] [Tool] Tolerate malformed UTF-8 in process streaming decoders (flutter/flutter#188453)
2026-06-29 [email protected] [flutter_tools] Use new ddc modules in test (flutter/flutter#188240)
2026-06-29 [email protected] Roll Packages from c1f7d92 to 656ccaa (12 revisions) (flutter/flutter#188728)
2026-06-29 [email protected] Remove unused fields (flutter/flutter#188705)
2026-06-29 [email protected] Clear text input handler widget on view dispose (flutter/flutter#188701)
2026-06-29 [email protected] Free compositor in view renderer finalize to avoid use-after-free (flutter/flutter#188702)
2026-06-29 [email protected] [linux] Use GWeakRef in mock signal handler test helper (flutter/flutter#188700)
2026-06-29 [email protected] Fixing few related editing issues with LTR/RTL text (flutter/flutter#188503)
2026-06-29 [email protected] [Flutter GPU] Add Texture.fromImage to wrap a ui.Image texture (flutter/flutter#188605)
2026-06-29 [email protected] [Flutter GPU] Honor the enable argument in RenderPass.setDepthWriteEnable (flutter/flutter#188715)
2026-06-29 [email protected] Roll Skia from ba1942d8c3e1 to 111e7582d081 (1 revision) (flutter/flutter#188721)
2026-06-29 [email protected] Roll Skia from 587d8befe1ee to ba1942d8c3e1 (6 revisions) (flutter/flutter#188717)
2026-06-29 [email protected] Remove some refs to package:intl (flutter/flutter#188504)
2026-06-29 [email protected] [VPAT] Update a11y assessment app FAB example to announce value change when it's updated. (flutter/flutter#188466)
...
kalyujniy pushed a commit to brickit-app/camera that referenced this pull request Jul 8, 2026
…flutter#12081)

Manual roll Flutter from 0c80830e465b to ca9f874f5284 (119 revisions)

Manual roll requested by [email protected]

flutter/flutter@0c80830...ca9f874

2026-06-30 [email protected] [tool] Don't require a Flutter compile task when staging jniLibs (flutter/flutter#188805)
2026-06-30 [email protected] [Impeller] Fix potential overflow when allocating buffers at the next power of two size (flutter/flutter#188742)
2026-06-30 [email protected] [Framework/Tool] Decouple preview theme imports (flutter/flutter#188176)
2026-06-30 [email protected] Add import of `dart:_js_interop_wasm` in sdk rewriter tool (flutter/flutter#188620)
2026-06-30 [email protected] Detach LLDB and print stack trace on process stop (flutter/flutter#188576)
2026-06-30 [email protected] [Linux] Fix FlCompositorOpenGL.pixels comment (flutter/flutter#188754)
2026-06-30 [email protected] [flutter_tools] Fix crash in flutter create when pubspec.yaml is empty (flutter/flutter#188385)
2026-06-30 [email protected] Roll Packages from 656ccaa to 274ed3e (23 revisions) (flutter/flutter#188792)
2026-06-30 [email protected] In AndroidImageGenerator, check that the destination pixel buffer has sufficient capacity for the decoded data (flutter/flutter#188752)
2026-06-30 [email protected] Roll pub packages (flutter/flutter#188773)
2026-06-30 [email protected] [Impeller] Add a flat VertexAttributeFormat for vertex inputs (flutter/flutter#188684)
2026-06-30 [email protected] Roll pub packages (flutter/flutter#188764)
2026-06-30 [email protected] Roll Dart SDK from 0cb483880b6b to e1bdb9ce3327 (2 revisions) (flutter/flutter#188763)
2026-06-29 [email protected] Handle 'no permissions' adb device state (flutter/flutter#187248)
2026-06-29 [email protected] [windows]: adjusts uniform buffers to hit hlsl optimization (flutter/flutter#188538)
2026-06-29 [email protected] Roll Skia from bfb7860cb9c7 to 71947c4110b0 (9 revisions) (flutter/flutter#188747)
2026-06-29 [email protected] ci: extract wait-for-engine-build logic into a reusable composite action (flutter/flutter#188748)
2026-06-29 [email protected] Provide guided migration logs when iOS app crashes on simulator (flutter/flutter#188736)
2026-06-29 [email protected] Revert "[flutter_tools] Track asset transformer dependencies for hot reload" (flutter/flutter#188751)
2026-06-29 [email protected] Migrate ABI splits to new AGP dsl (flutter/flutter#188369)
2026-06-29 [email protected] Add Impeller+OpenGLES startup benchmark for mokey (flutter/flutter#188495)
2026-06-29 [email protected] Increase macOS minimum supported version from 10.15 to 12 to support Xcode 27  (flutter/flutter#188520)
2026-06-29 [email protected] Moves test ownership validation to flutter/flutter (flutter/flutter#188655)
2026-06-29 [email protected] Add --flavor support for Windows desktop builds (flutter/flutter#187034)
2026-06-29 [email protected] Android_hardware_smoke_test: Enable pixel exact local file comparator to read goldens from flutter asset URI (flutter/flutter#188587)
2026-06-29 [email protected] [flutter_tools] Use DeviceHub.app for iOS simulator path on Xcode 27+ (flutter/flutter#187910)
2026-06-29 [email protected] Roll Skia from 111e7582d081 to bfb7860cb9c7 (2 revisions) (flutter/flutter#188731)
2026-06-29 [email protected] Use `revert` label instead of `revert_wf` (flutter/flutter#188639)
2026-06-29 [email protected] Properly await Dart Development Service shutdown with timeout (flutter/flutter#188387)
2026-06-29 [email protected] [flutter_tools] Track asset transformer dependencies for hot reload (flutter/flutter#187947)
2026-06-29 [email protected] [Tool] Tolerate malformed UTF-8 in process streaming decoders (flutter/flutter#188453)
2026-06-29 [email protected] [flutter_tools] Use new ddc modules in test (flutter/flutter#188240)
2026-06-29 [email protected] Roll Packages from c1f7d92 to 656ccaa (12 revisions) (flutter/flutter#188728)
2026-06-29 [email protected] Remove unused fields (flutter/flutter#188705)
2026-06-29 [email protected] Clear text input handler widget on view dispose (flutter/flutter#188701)
2026-06-29 [email protected] Free compositor in view renderer finalize to avoid use-after-free (flutter/flutter#188702)
2026-06-29 [email protected] [linux] Use GWeakRef in mock signal handler test helper (flutter/flutter#188700)
2026-06-29 [email protected] Fixing few related editing issues with LTR/RTL text (flutter/flutter#188503)
2026-06-29 [email protected] [Flutter GPU] Add Texture.fromImage to wrap a ui.Image texture (flutter/flutter#188605)
2026-06-29 [email protected] [Flutter GPU] Honor the enable argument in RenderPass.setDepthWriteEnable (flutter/flutter#188715)
2026-06-29 [email protected] Roll Skia from ba1942d8c3e1 to 111e7582d081 (1 revision) (flutter/flutter#188721)
2026-06-29 [email protected] Roll Skia from 587d8befe1ee to ba1942d8c3e1 (6 revisions) (flutter/flutter#188717)
2026-06-29 [email protected] Remove some refs to package:intl (flutter/flutter#188504)
2026-06-29 [email protected] [VPAT] Update a11y assessment app FAB example to announce value change when it's updated. (flutter/flutter#188466)
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

flutter test integration tests hang at teardown — _ddsLauncher.shutdown() is fire-and-forget with no timeout (sibling of #187785)

2 participants