Skip to content

[flutter_tools] Guard socket streams and done futures against socket reset errors - #192941

Merged
auto-submit[bot] merged 8 commits into
flutter:masterfrom
bkonyi:issue-192935
Sep 29, 2026
Merged

auto-submit[bot] merged 8 commits into
flutter:masterfrom
bkonyi:issue-192935

Conversation

@bkonyi

@bkonyi bkonyi commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

When remote peers abruptly terminate or reset network connections, POSIX event handlers (such as epoll) trigger low-level socket reset errors (SocketException: Error event raised in event handler : error condition has been reset, port = 0) via _NativeSocket.multiplex.

If these socket error events occur on streams or sink done futures that lack error handlers, or when adding to/closing sinks in an error state, the unhandled exception escapes into the Zone and causes Flutter tool crashes.

This change:

  • Introduces FutureErrorHandling<T> in packages/flutter_tools/lib/src/base/common.dart to provide a reusable .handleError(...) extension on Future for background futures without requiring empty (_) {} callbacks.
  • Guards createVmServiceDelegate channel streams, sink done futures, and sink operations against SocketException.
  • Guards DaemonStreams.fromSocket, DaemonStreams.connect, and daemon server socket.done and socket.addStream futures.
  • Adds onError handling to ProxiedPortForwarder forwarded socket streams.
  • Adds onError handling to ResidentRunner log streams.
  • Adds error handling to AndroidConsole socket done future on connect and destroy.
  • Adds unit tests for FutureErrorHandling.handleError (including test predicate filtering) and regression tests verifying that socket stream and done future errors do not crash the tool.

Fixes #192935

Pre-launch Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I signed the [CLA].
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is [test-exempt].
  • I followed the [breaking change policy] and added [Data Driven Fixes] where supported.
  • All existing and new tests are passing.

…reset errors

When remote peers abruptly terminate or reset network connections, POSIX event
handlers (such as epoll) trigger low-level socket reset errors
(`SocketException: Error event raised in event handler : error condition has been reset, port = 0`)
via `_NativeSocket.multiplex`.

If these socket error events occur on streams or sink `done` futures that lack
error handlers, or when adding to/closing sinks in an error state, the unhandled
exception escapes into the Zone and causes Flutter tool crashes.

This change:
- Introduces `FutureErrorHandling<T>` in `packages/flutter_tools/lib/src/base/common.dart` to provide a reusable `.handleError(...)` extension on `Future` for background futures without requiring empty `(_) {}` callbacks.
- Guards `createVmServiceDelegate` channel streams, sink `done` futures, and sink operations against `SocketException`.
- Guards `DaemonStreams.fromSocket`, `DaemonStreams.connect`, and daemon server `socket.done` and `socket.addStream` futures.
- Adds `onError` handling to `ProxiedPortForwarder` forwarded socket streams.
- Adds `onError` handling to `ResidentRunner` log streams.
- Adds error handling to `AndroidConsole` socket `done` future on connect and destroy.
- Adds unit tests for `FutureErrorHandling.handleError` (including `test` predicate filtering) and regression tests verifying that socket stream and done future errors do not crash the tool.

Fixes flutter#192935
@bkonyi bkonyi added the CICD Run CI/CD label Sep 17, 2026
@github-actions github-actions Bot added tool Affects the "flutter" command-line tool. See also t: labels. team-android Owned by Android platform team labels Sep 17, 2026
…atch StateError on VM service sink

- Update `FutureErrorHandling.handleError` to rethrow unmatched errors via `Error.throwWithStackTrace` when `test` evaluates to `false`.
- Catch `Object` (covering both `Exception` and `StateError`) around `channel.add` and `channel.close` in `createVmServiceDelegate`.
- Add unit tests verifying unmatched error rethrowing and synchronous `StateError` handling.
…tion, and injected logger

- Replace `dynamic` with `Object?` on VM service channel streams and test `FakeWebSocket` signatures.
- Move collection generic type parameters to the RHS list literals in `daemon_test.dart` and `vmservice_test.dart`.
- Convert `DaemonStreams.fromSocket` to a `factory` constructor delegating to `DaemonStreams(socket, socket, logger: logger)`.
- Inject `Logger` into `FlutterDevice` (`_logger`) and use `_logger.printTrace` instead of `globals.printTrace`.
- Use `_` wildcards for unused callback parameters and use `.handleError` extension in `vmservice_test.dart`.
…ogger fallback

- Use nullable `this._logger` initializer on `FlutterDevice` and pass `logger: logger` from `FlutterDevice.create`.
- Call `_logger?.printTrace` in `startEchoingDeviceLog` to avoid introducing any new `globals.logger` references.
…tch clauses, and clean up test fakes

- Override `done` on fake AndroidConsole sockets in `android_device_test.dart` and add a unit test for `socket.done` completing with `SocketException`.
- Revert `FlutterDevice` constructor signature in `resident_runner.dart` and use `globals.printTrace` in `startEchoingDeviceLog`.
- Narrow `on Object catch` in `createVmServiceDelegate` to `on Exception` and `on StateError`, and close the channel when a write fails.
- Remove unused fields and methods from `FakeSocket` in `daemon_test.dart` and `FakeWebSocket` in `vmservice_test.dart`.
…done fields on fake sockets

- Omit unused `catch (_)` in `handleWriteError` and extract `logCloseError` helper in `disposeHandler` in `vmservice.dart`.
- Use `@override final Future<void> done` fields on fake Android console sockets in `android_device_test.dart`.
@bkonyi
bkonyi marked this pull request as ready for review September 21, 2026 18:46
@bkonyi
bkonyi requested a review from a team as a code owner September 21, 2026 18:46
@bkonyi
bkonyi requested review from camsim99 and removed request for a team September 21, 2026 18:46

@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 introduces a custom FutureErrorHandling extension on Future to handle errors on background sink and socket completion futures, applying it across several files and adding corresponding unit tests. The code review suggests removing this custom extension entirely to avoid unnecessary complexity and potential confusion, recommending instead the use of standard Dart APIs like catchError or then().catchError() at the call sites, along with removing the associated unit tests and imports.

Comment thread packages/flutter_tools/lib/src/base/common.dart
Comment thread packages/flutter_tools/lib/src/android/android_console.dart
Comment thread packages/flutter_tools/lib/src/android/android_console.dart
Comment thread packages/flutter_tools/lib/src/commands/daemon.dart
Comment thread packages/flutter_tools/lib/src/daemon.dart
Comment thread packages/flutter_tools/lib/src/vmservice.dart
Comment thread packages/flutter_tools/lib/src/vmservice.dart
Comment thread packages/flutter_tools/test/general.shard/base/common_test.dart
Comment thread packages/flutter_tools/test/general.shard/vmservice_test.dart
Comment thread packages/flutter_tools/test/general.shard/vmservice_test.dart
…orHandling.handleError

- Explain in `FutureErrorHandling.handleError`'s doc comment why `Future.then` is used instead of `Future.catchError` or `Future.onError` (`AvoidFutureCatchError` custom analyzer rule in `dev/bots/custom_rules/avoid_future_catcherror.dart`, flutter#130662, dart-lang/sdk#51248).
camsim99
camsim99 previously approved these changes Sep 28, 2026

@camsim99 camsim99 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.

Looks reasonable to me!

@bkonyi bkonyi added the autosubmit Merge PR when tree becomes green via auto submit App label Sep 29, 2026
@bkonyi

bkonyi commented Sep 29, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @camsim99! 😁

@auto-submit
auto-submit Bot added this pull request to the merge queue Sep 29, 2026
Merged via the queue into flutter:master with commit 668977b Sep 29, 2026
23 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Sep 29, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Sep 30, 2026
flutter/flutter@55b8f88...d649d2b

2026-09-30 43054281+camsim99@users.noreply.github.com [Android] Update the CLI to reject passing engine configuration flags with a prebuilt binary in release mode (flutter/flutter#190870)
2026-09-30 engine-flutter-autoroll@skia.org Roll Skia from af1e8b356dd1 to c7b323126bf0 (1 revision) (flutter/flutter#193569)
2026-09-30 zhongliu88889@gmail.com [web] Respect text affinity in getLineBoundary at a soft wrap (flutter/flutter#192664)
2026-09-30 bkonyi@google.com [tool] Migrate TestCommand and platform runner to modular dependency injection (flutter/flutter#190789)
2026-09-30 engine-flutter-autoroll@skia.org Roll Skia from 3a20a0464d25 to af1e8b356dd1 (1 revision) (flutter/flutter#193564)
2026-09-30 engine-flutter-autoroll@skia.org Roll Skia from 554ef62d11a9 to 3a20a0464d25 (6 revisions) (flutter/flutter#193556)
2026-09-30 116356835+AbdeMohlbi@users.noreply.github.com Use null aware elements in `platform_views.dart` (flutter/flutter#193214)
2026-09-30 116356835+AbdeMohlbi@users.noreply.github.com Replace deprecated `withOpacity` in `flutter_logo.dart` (flutter/flutter#192583)
2026-09-30 engine-flutter-autoroll@skia.org Roll Skia from f441ca223b2b to 554ef62d11a9 (72 revisions) (flutter/flutter#193548)
2026-09-30 joel.winarske@linux.com Fix StrcmpFixed matching prefixes in the Vulkan embedder tests (flutter/flutter#192999)
2026-09-30 jesswon@google.com Update Engine to test Android 17 AVD (flutter/flutter#193239)
2026-09-29 joel.winarske@linux.com Give the Vulkan test context the extensions Impeller requires (flutter/flutter#193002)
2026-09-29 55765052+MohanadAbdallah-mv@users.noreply.github.com Rename "subtext" to "supportingTextPadding" in `FormField`'s documentation (flutter/flutter#183582)
2026-09-29 markzipan@google.com Set --no-js-strongly-connected-components for DDC compiles by default (flutter/flutter#193485)
2026-09-29 jesswon@google.com Split pre-AGP 8.3 module AAR test into a Java 17 pinned target (flutter/flutter#193467)
2026-09-29 32538273+ValentinVignal@users.noreply.github.com Remove no-shuffle from gen_defaults_test (flutter/flutter#192280)
2026-09-29 katelovett@google.com Update guidance on bumping Dart (flutter/flutter#193131)
2026-09-29 dbebawy@users.noreply.github.com Remove vestigial `download_jdk` gclient var (flutter/flutter#188571)
2026-09-29 137456488+flutter-pub-roller-bot@users.noreply.github.com Roll pub packages (flutter/flutter#193522)
2026-09-29 bkonyi@google.com [flutter_tools] Lazily initialize AndroidSdk platform and build-tools discovery (flutter/flutter#191972)
2026-09-29 bkonyi@google.com [tool] Migrate Web build subcommands and toolchain to modular dependency injection (flutter/flutter#190783)
2026-09-29 matt.boetger@gmail.com Pin androidx.test dependencies in integration_test (flutter/flutter#193316)
2026-09-29 Deil.Christoph@gmail.com [flutter_tools] Include flutter.js.map in web builds (flutter/flutter#192257)
2026-09-29 Rusino@users.noreply.github.com [WebParagraph] Fixing edge cases for wrapping text (with newlines) (flutter/flutter#189858)
2026-09-29 ryjohn@google.com Bump customer testing version for flutter/devtools update (flutter/flutter#193511)
2026-09-29 engine-flutter-autoroll@skia.org Roll Packages from ba0364a to 3c6ce59 (14 revisions) (flutter/flutter#193507)
2026-09-29 bkonyi@google.com [flutter_tools] Guard socket streams and done futures against socket reset errors (flutter/flutter#192941)

If this roll has caused a breakage, revert this CL and set the roller
to dry run mode using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC quncheng@google.com,stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD team-android Owned by Android platform team tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[tool_crash] SocketException (Error event raised in event handler : error condition has been reset, port = 0) in _NativeSocket.multiplex

2 participants