
Fixes https://github.com/flutter/flutter/issues/163104 The core issue is that `EmbedderTaskRunner` can schedule things in advance, but there is no checking if the task is stale when executing it. It is possible that `FlutterEngineRunTask` will attempt to run the task on engine that is non null but already being deallocated. This in not a problem for raster and platform task runners, because raster task runner shouldn't have any scheduled tasks after shutdown and platform task runner executes the shutdown process, so the pointer is always either valid or null, but it is an issue for custom `ui_task_runner`, because it may be calling `FlutterEngineRunTask` with engine pointer that is not yet null but already shutting down. The proposed solution is to assign a unique identifier for each `EmbedderTaskRunner`, use this identifier as the `runner` field inside `FlutterTask` instead of casting the address of the runner, and verify that this identifier is valid inside `FlutterEngineRunTask` before calling anything on the engine. Special care needs to be done to not invalidate the unique identifier while `ui_task_runner` is running a task as it may lead to raciness. See `EmbedderEngine::CollectThreadHost()`. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
Flutter Engine
Setting up the Engine development environment
See here
gclient
bootstrap
Flutter engine uses gclient
to manage dependencies.
If you've already cloned the flutter repository: