close
Skip to content

[mime] Fix hanging part streams on source stream error or completion#2429

Open
iv-re wants to merge 1 commit into
dart-lang:mainfrom
iv-re:fix-mime-hanging-parts
Open

[mime] Fix hanging part streams on source stream error or completion#2429
iv-re wants to merge 1 commit into
dart-lang:mainfrom
iv-re:fix-mime-hanging-parts

Conversation

@iv-re

@iv-re iv-re commented Jun 21, 2026

Copy link
Copy Markdown

Fixes #2428

Propagate source stream errors and premature close events (MimeMultipartException) to the active part stream (_multipartController) and close it. This prevents listeners of the active part from hanging indefinitely.

Adds corresponding tests in mime_multipart_transformer_test.dart.


  • I’ve reviewed the contributor guide and applied the relevant portions to this PR.
Contribution guidelines:

Many Dart repos have a weekly cadence for reviewing PRs - please allow for some latency before initial review feedback.

Note: The Dart team is trialing Gemini Code Assist. Don't take its comments as final Dart team feedback. Use the suggestions if they're helpful; otherwise, wait for a human reviewer.

@iv-re
iv-re requested a review from lrhn as a code owner June 21, 2026 15:04

@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 updates BoundMultipartStream to properly handle errors and premature onDone events from the source stream, preventing hangs by ensuring the active multipart controller is closed and notified. It also adds comprehensive tests to verify this behavior. The reviewer identified a potential bug where a null assertion failure could occur if the source stream continues to emit data after an error, and suggested setting _state = _failCode in the onError handler to prevent further parsing.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread pkgs/mime/lib/src/bound_multipart_stream.dart
@iv-re
iv-re force-pushed the fix-mime-hanging-parts branch from 47b402d to 3168426 Compare June 21, 2026 15:08
@github-actions

Copy link
Copy Markdown

Package publishing

Package Version Status Publish tag (post-merge)
package:api_summary 0.1.0-wip WIP (no publish necessary)
package:bazel_worker 1.1.5 already published at pub.dev
package:benchmark_harness 2.4.0 already published at pub.dev
package:boolean_selector 2.1.2 already published at pub.dev
package:browser_launcher 1.2.0-wip WIP (no publish necessary)
package:cli_config 0.2.1-wip WIP (no publish necessary)
package:cli_util 0.5.1 already published at pub.dev
package:clock 1.1.3-wip WIP (no publish necessary)
package:code_builder 4.12.0-wip WIP (no publish necessary)
package:coverage 1.15.1 already published at pub.dev
package:csslib 1.0.2 already published at pub.dev
package:extension_discovery 2.1.0 already published at pub.dev
package:file 7.0.2-wip WIP (no publish necessary)
package:file_testing 3.1.0-wip WIP (no publish necessary)
package:glob 2.1.3 already published at pub.dev
package:graphs 2.4.0-wip WIP (no publish necessary)
package:html 0.15.7-wip WIP (no publish necessary)
package:io 1.1.0-wip WIP (no publish necessary)
package:json_rpc_2 4.1.0 already published at pub.dev
package:markdown 7.4.0 ready to publish markdown-v7.4.0
package:mime 2.1.0-wip WIP (no publish necessary)
package:oauth2 2.0.5 already published at pub.dev
package:package_config 3.0.0 already published at pub.dev
package:pool 1.5.3-wip WIP (no publish necessary)
package:process 5.0.5 (error) pubspec version (5.0.5) and changelog (5.0.6-wip) don't agree
package:pub_semver 2.2.0 already published at pub.dev
package:pubspec_parse 1.6.0-wip WIP (no publish necessary)
package:source_map_stack_trace 2.1.3-wip WIP (no publish necessary)
package:source_maps 0.10.14-wip WIP (no publish necessary)
package:source_span 1.10.2 already published at pub.dev
package:sse 4.2.0 already published at pub.dev
package:stack_trace 1.12.2-wip (error) pubspec version (1.12.2-wip) and changelog (1.12.2-dev) don't agree
package:stream_channel 2.1.4 already published at pub.dev
package:stream_transform 2.1.2-wip WIP (no publish necessary)
package:string_scanner 1.4.2-wip WIP (no publish necessary)
package:term_glyph 1.2.3-wip WIP (no publish necessary)
package:test_reflective_loader 0.6.0 ready to publish test_reflective_loader-v0.6.0
package:timing 1.0.2 already published at pub.dev
package:unified_analytics 8.0.15 already published at pub.dev
package:watcher 1.2.2-wip WIP (no publish necessary)
package:yaml 3.1.4-wip WIP (no publish necessary)
package:yaml_edit 2.2.4 already published at pub.dev

Documentation at https://github.com/dart-lang/ecosystem/wiki/Publishing-automation.

@github-actions

Copy link
Copy Markdown

PR Health

Unused Dependencies ✔️
Package Status
mime ✔️ All dependencies utilized correctly.

For details on how to fix these, see dependency_validator.

This check can be disabled by tagging the PR with skip-unused-dependencies-check.

Breaking changes ✔️
Package Change Current Version New Version Needed Version Looking good?
mime None 2.0.0 2.1.0-wip 2.1.0-wip ✔️

This check can be disabled by tagging the PR with skip-breaking-check.

API leaks ✔️

The following packages contain symbols visible in the public API, but not exported by the library. Export these symbols or remove them from your publicly visible API.

Package Leaked API symbol Leaking sources

This check can be disabled by tagging the PR with skip-leaking-check.

Changelog Entry
Package Changed Files
package:mime pkgs/mime/lib/src/bound_multipart_stream.dart

Changes to files need to be accounted for in their respective changelogs.

This check can be disabled by tagging the PR with skip-changelog-check.

Coverage ✔️
File Coverage
pkgs/mime/lib/src/bound_multipart_stream.dart 💚 89 % ⬆️ 1 %

This check for test coverage is informational (issues shown here will not fail the PR).

This check can be disabled by tagging the PR with skip-coverage-check.

License Headers ✔️
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

Files
no missing headers

All source files should start with a license header.

Unrelated files missing license headers
Files
pkgs/bazel_worker/benchmark/benchmark.dart
pkgs/coverage/lib/src/coverage_options.dart
pkgs/html/example/main.dart
pkgs/pubspec_parse/test/git_uri_test.dart
pkgs/watcher/test/custom_watcher_factory_test.dart

This check can be disabled by tagging the PR with skip-license-check.

@lrhn lrhn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No opinion on whether this is a good change, I don't know the code well enough. Just nit-picking on style.

Comment thread pkgs/mime/lib/src/bound_multipart_stream.dart Outdated
Comment thread pkgs/mime/lib/src/bound_multipart_stream.dart
_multipartController!.addError(_exceptionBadEnding);
}
_multipartController!.close();
_multipartController = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No _tryPropagateControllerState(); here, like in line 146?

Is it not needed when _controller is being closed immediately after?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

_tryPropagateControllerState() syncs the main controller's state (pause/resume/cancel) to _subscription.

In onDone, the source stream is already finished and _subscription is dead, making any synchronization or cancellation calls on it redundant.

@iv-re
iv-re force-pushed the fix-mime-hanging-parts branch from 3168426 to ef9deac Compare June 22, 2026 12:04
@lrhn
lrhn requested review from lrhn and removed request for lrhn July 6, 2026 13:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MimeMultipartTransformer: active part stream hangs indefinitely on source stream error or unexpected done

2 participants