Repository navigation
Check for a null codec in MultiFrameImageStreamCompleter after calling _emitFrame - #165009
Merged
Merged
Conversation
…g _emitFrame _emitFrame invokes image listeners. A listener callback could remove all of the MultiFrameImageStreamCompleter's listeners, resulting in a _maybeDispose call that destroys the codec. Fixes flutter#164944 Fixes flutter#164537
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 12, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 12, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 13, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 13, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 13, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 13, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 13, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 13, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 13, 2025
…r calling _emitFrame (flutter/flutter#165009)
This was referenced Mar 13, 2025
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 14, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 16, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 16, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 17, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 20, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 25, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 25, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 26, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 26, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 26, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 26, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 26, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 26, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 26, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 26, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 27, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 27, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 27, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 27, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 27, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 27, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 27, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 27, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
Mar 28, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
May 20, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
May 20, 2025
…r calling _emitFrame (flutter/flutter#165009)
engine-flutter-autoroll
added a commit
to engine-flutter-autoroll/packages
that referenced
this pull request
May 21, 2025
…r calling _emitFrame (flutter/flutter#165009)
romanejaquez
pushed a commit
to romanejaquez/flutter
that referenced
this pull request
Aug 14, 2025
…g _emitFrame (flutter#165009) _emitFrame invokes image listeners. A listener callback could remove all of the MultiFrameImageStreamCompleter's listeners, resulting in a _maybeDispose call that destroys the codec. Fixes flutter#164944 Fixes flutter#164537
9 tasks
richyo-codes
pushed a commit
to richyo-codes/flutter
that referenced
this pull request
Oct 8, 2026
… when a listener is re-added (flutter#193575) **Title:** Fix null `_nextFrame` in `MultiFrameImageStreamCompleter._handleAppFrame` when a listener is re-added --- `MultiFrameImageStreamCompleter._handleAppFrame` can run after its decoded frame has been thrown away. When that happens it dereferences a null `_nextFrame`. In debug builds this fails the `_nextFrame != null` assertion; in release builds it throws `Null check operator used on a null value`. ### How it happens 1. A frame is decoded and `_handleAppFrame` is scheduled as a frame callback. 2. Before that frame runs, the stream drops to zero listeners and a listener is added back. `_ImageState` does this whenever `TickerMode` changes, for example during a route push or pop. Something must keep the completer alive while it has no listeners, as `ImageCache` does. 3. `removeListener` cancels only `_timer`. It does not cancel the pending frame callback. 4. `addListener` calls `_decodeNextFrameAndSchedule()`. That synchronously disposes `_nextFrame` and sets it to null before it awaits the next frame. 5. The pending `_handleAppFrame` then runs with listeners present and `_nextFrame == null`. flutter#30346 fixed flutter#30340 by stopping `_handleAppFrame` from being registered twice (`_frameCallbackScheduled`). It did not handle the callback that is already pending when decoding restarts; that PR's test for this scenario was merged disabled. The same failure was reported again in flutter#122576. ### Fix `_handleAppFrame` now returns early when `_nextFrame` is null. The restarted decode sets `_nextFrame` and calls `_scheduleAppFrame()` when it completes. `_frameCallbackScheduled` has already been reset at that point, so the animation resumes on the next frame. The only visible effect is one skipped animation frame instead of an exception. This follows the same pattern as the `_codec == null` check added in flutter#165009. We see this crash in production in several apps that treat framework errors as fatal. The trigger is animated images that are on screen during route transitions. ### Tests Adds `re-adding a listener while a frame callback is pending does not crash` to `image_stream_test.dart`. It reproduces the race without depending on timing: - Without the fix it fails with `Failed assertion: line 1064 pos 12: '_nextFrame != null'`. - With the fix it passes, and the animation resumes once the restarted decode completes. - All other tests in `image_stream_test.dart` still pass. Fixes flutter#30340 Related: flutter#122576, flutter#30346 ## 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. <!-- Keep the checklist link references from the upstream PR template. -->
suryaKommana2662
pushed a commit
to suryaKommana2662/flutter
that referenced
this pull request
Oct 29, 2026
… when a listener is re-added (flutter#193575) **Title:** Fix null `_nextFrame` in `MultiFrameImageStreamCompleter._handleAppFrame` when a listener is re-added --- `MultiFrameImageStreamCompleter._handleAppFrame` can run after its decoded frame has been thrown away. When that happens it dereferences a null `_nextFrame`. In debug builds this fails the `_nextFrame != null` assertion; in release builds it throws `Null check operator used on a null value`. ### How it happens 1. A frame is decoded and `_handleAppFrame` is scheduled as a frame callback. 2. Before that frame runs, the stream drops to zero listeners and a listener is added back. `_ImageState` does this whenever `TickerMode` changes, for example during a route push or pop. Something must keep the completer alive while it has no listeners, as `ImageCache` does. 3. `removeListener` cancels only `_timer`. It does not cancel the pending frame callback. 4. `addListener` calls `_decodeNextFrameAndSchedule()`. That synchronously disposes `_nextFrame` and sets it to null before it awaits the next frame. 5. The pending `_handleAppFrame` then runs with listeners present and `_nextFrame == null`. flutter#30346 fixed flutter#30340 by stopping `_handleAppFrame` from being registered twice (`_frameCallbackScheduled`). It did not handle the callback that is already pending when decoding restarts; that PR's test for this scenario was merged disabled. The same failure was reported again in flutter#122576. ### Fix `_handleAppFrame` now returns early when `_nextFrame` is null. The restarted decode sets `_nextFrame` and calls `_scheduleAppFrame()` when it completes. `_frameCallbackScheduled` has already been reset at that point, so the animation resumes on the next frame. The only visible effect is one skipped animation frame instead of an exception. This follows the same pattern as the `_codec == null` check added in flutter#165009. We see this crash in production in several apps that treat framework errors as fatal. The trigger is animated images that are on screen during route transitions. ### Tests Adds `re-adding a listener while a frame callback is pending does not crash` to `image_stream_test.dart`. It reproduces the race without depending on timing: - Without the fix it fails with `Failed assertion: line 1064 pos 12: '_nextFrame != null'`. - With the fix it passes, and the animation resumes once the restarted decode completes. - All other tests in `image_stream_test.dart` still pass. Fixes flutter#30340 Related: flutter#122576, flutter#30346 ## 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. <!-- Keep the checklist link references from the upstream PR template. -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
_emitFrame invokes image listeners. A listener callback could remove all of the MultiFrameImageStreamCompleter's listeners, resulting in a _maybeDispose call that destroys the codec.
Fixes #164944
Fixes #164537