Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@chinmaygarde
Copy link
Member

Also creates a new test harness for the desktop embedder framework target and adds a test that launches a headless engine in this new thread configuration.

Fixes flutter/flutter#17579

@chinmaygarde
Copy link
Member Author

@franciscojma86, @stuartmorgan When you are back, can we figure out how to make the test harness more thorough? There also needs to be some guidance on managing the lifecycle of the FlutterEngine.

Copy link
Contributor

@stuartmorgan-g stuartmorgan-g left a comment

Choose a reason for hiding this comment

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

Haven't had time for a full review, but flagged a few things in a quick skim.

* Instead of looking up the assets and ICU data path in the application bundle, this initializer
* allows callers to create a Dart project with custom locations specified for the both.
*/
- (_Nonnull instancetype)initWithAssetsPath:(NSString* _Nonnull)assets
Copy link
Contributor

Choose a reason for hiding this comment

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

Prefer nonnull to _Nonnull when possible (such as here) for consistency with the other macOS framework code.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

@implementation FlutterDartProject {
NSBundle* _dartBundle;
NSString* _assetsPath;
NSString* _icuDataPath;
Copy link
Contributor

Choose a reason for hiding this comment

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

_ICUDataPath

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

}

// Balancing release for the retain in the task runner dispatch table.
CFRelease((CFTypeRef)self);
Copy link
Contributor

Choose a reason for hiding this comment

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

The declaration comment above can't possibly be correct with this change, because dealloc won't be called as long as this reference exists. So it seems like this makes it impossible to clean up engine instances.

Copy link
Member Author

Choose a reason for hiding this comment

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

My expectation was that when the view controller goes away, it will reset its association with the FlutterEngine via engine.viewController = nil; which would have shutdown the engine explicitly. But you're right that this is a leak now as that doesn't seem to be happening. The expectation is that the engine needs to be shut down explicitly. I'll rework this.


#pragma mark - Task runner integration

- (void)postMainThreadTask:(FlutterTask)task targetTimeNanos:(uint64_t)target_time {
Copy link
Contributor

Choose a reason for hiding this comment

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

macOS framework style is to pre-declare at the top of the file, with a declaration comment, all private methods.


#pragma mark - Task runner integration

- (void)postMainThreadTask:(FlutterTask)task targetTimeNanos:(uint64_t)target_time {
Copy link
Contributor

Choose a reason for hiding this comment

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

targetTime

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.


#pragma mark - Task runner integration

- (void)postMainThreadTask:(FlutterTask)task targetTimeNanos:(uint64_t)target_time {
Copy link
Contributor

Choose a reason for hiding this comment

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

targetTimeInNanoseconds: (abbreviation is strongly discouraged in ObjC)

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

if (result != kSuccess) {
NSLog(@"Could not post a task to the Flutter engine.");
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be also logged as a failure?

Copy link
Member Author

Choose a reason for hiding this comment

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

This should not happen at all because timed tasks are not posted to the platform or render task runners and untimed tasks are awaited upon during shell shutdown. But yeah, not giving all the tasks back to the engine is a small leak of the task handle.

…re the platform and render task runners are the same.

Also creates a new test harness for the desktop embedder framework target and adds a test that launches a headless engine in this new thread configuration.

Fixes flutter/flutter#17579
@chinmaygarde
Copy link
Member Author

I cleared @franciscojma86 review. This isn't good to go yet with the explicit shutdown being now necessary.

@chinmaygarde
Copy link
Member Author

@keithbrianptomo Can you elaborate?

@chinmaygarde
Copy link
Member Author

Hmm, I tried really hard to figure out a way to safely shut down the embedder instance of the Flutter engine automatically on dealloc. However, there is no way to make it thread safe.

The next bit is tricky because both the Obj-C & C instances of the engine object are called FlutterEngine

The FlutterEngine Obj-C instance needs to be accessed from other threads while it is being deallocated. This is because the FlutterEngine C instance may post tasks during FlutterEngine Obj-C instance shutdown. Accessing the Obj-C instance from other thread during deallocation is not safe (specifically the weak handle generation). The runtime correctly warns of this error.

Now, my patch doesn't actually introduce a leak because deallocating the view controller will set the engines view controller property to nil. This, in turn, will shutdown the engine. Thereby releasing the strong reference.

While using the view controller directly wont result in a leak, I understand that folks using the FlutterEngine instance directly now need a way to shutdown the engine explicitly lest they introduce a leak. To address this, I have moved shutdownEngine to be a public API call on FlutterEngine and tested the same.

I believe with these changes and requirements on the use of the FlutterEngine, the lifecycle management is thread safe and leak free. PTAL.

Copy link
Contributor

@franciscojma86 franciscojma86 left a comment

Choose a reason for hiding this comment

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

LGTM

@chinmaygarde chinmaygarde merged commit e3c5f48 into flutter:master Oct 28, 2019
@chinmaygarde chinmaygarde deleted the no_resize_crash branch October 28, 2019 19:47
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 28, 2019
…tion where the platform and render task runners are the same. (flutter/engine#13300)
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 28, 2019
…tion where the platform and render task runners are the same. (flutter/engine#13300)
engine-flutter-autoroll added a commit to flutter/flutter that referenced this pull request Oct 29, 2019
[email protected]:flutter/engine.git/compare/c3b63d610b07...49971e2

git log c3b63d6..49971e2 --no-merges --oneline
2019-10-28 [email protected] Implement basic Picture.toImage via BitmapCanvas (flutter/engine#13391)
2019-10-28 [email protected] Switch the MacOS Desktop embedder to using a thread configuration where the platform and render task runners are the same. (flutter/engine#13300)
2019-10-28 [email protected] Roll src/third_party/skia 18f5b1a6dd77..1beb8ae9a2f5 (9 commits) (flutter/engine#13392)


If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-engine-flutter-autoroll
Please CC [email protected] on the revert to ensure that a human
is aware of the problem.

To report a problem with the AutoRoller itself, please file a bug:
https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+/master/autoroll/README.md
Inconnu08 pushed a commit to Inconnu08/flutter that referenced this pull request Nov 26, 2019
[email protected]:flutter/engine.git/compare/c3b63d610b07...49971e2

git log c3b63d6..49971e2 --no-merges --oneline
2019-10-28 [email protected] Implement basic Picture.toImage via BitmapCanvas (flutter/engine#13391)
2019-10-28 [email protected] Switch the MacOS Desktop embedder to using a thread configuration where the platform and render task runners are the same. (flutter/engine#13300)
2019-10-28 [email protected] Roll src/third_party/skia 18f5b1a6dd77..1beb8ae9a2f5 (9 commits) (flutter/engine#13392)


If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-engine-flutter-autoroll
Please CC [email protected] on the revert to ensure that a human
is aware of the problem.

To report a problem with the AutoRoller itself, please file a bug:
https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+/master/autoroll/README.md
auto-submit bot pushed a commit that referenced this pull request Nov 8, 2024
Adds a `destruction_callback` member to `FlutterTaskRunnerDescription` that provides embedder developers a means of performing any cleanup of resources tied to the lifetime of the task runner.

In the case of the macOS embedder, the task runner holds a reference to the engine itself that is used in the `post_task_callback` and whose lifetime needs to match/exceed that of the task runner. This refactoring allows us to centralise all related retain count manipulation around task runner setup.

This is a refactor of the lifecycle bits of #13300.

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
nick9822 pushed a commit to nick9822/flutter that referenced this pull request Dec 18, 2024
…#56445)

Adds a `destruction_callback` member to `FlutterTaskRunnerDescription` that provides embedder developers a means of performing any cleanup of resources tied to the lifetime of the task runner.

In the case of the macOS embedder, the task runner holds a reference to the engine itself that is used in the `post_task_callback` and whose lifetime needs to match/exceed that of the task runner. This refactoring allows us to centralise all related retain count manipulation around task runner setup.

This is a refactor of the lifecycle bits of flutter/engine#13300.

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Crash under sendIndexedMeshToGpu when resizing macOS embedder

4 participants