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

Conversation

@jonahwilliams
Copy link
Contributor

The display link and/or notification observer was keeping the FlutterMetalLayer alive. Add an invalidate method and call it in the IOSSurface dtor.

How do we test this?

@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact "@test-exemption-reviewer" in the #hackers channel in Chat (don't just cc them here, they won't see it! Use Discord!).

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@jonahwilliams
Copy link
Contributor Author

alternatively we could say that the devicelab tests not immediately crashing demonstrates that this works :)

@jmagman
Copy link
Member

jmagman commented Jul 25, 2024

How do we test this?

Check out:

- (void)testReleasesLinkOnInvalidation {
__weak CADisplayLink* weakLink;
@autoreleasepool {
auto thread_task_runner = CreateNewThread("VsyncWaiterIosTest");
VSyncClient* vsyncClient = [[VSyncClient alloc]
initWithTaskRunner:thread_task_runner
callback:[](std::unique_ptr<flutter::FrameTimingsRecorder> recorder) {}];
weakLink = [vsyncClient getDisplayLink];
XCTAssertNotNil(weakLink);
[vsyncClient invalidate];
}
// VSyncClient has released the CADisplayLink.
XCTAssertNil(weakLink);
}

VsyncWaiterIOS::~VsyncWaiterIOS() {
// This way, we will get no more callbacks from the display link that holds a weak (non-nilling)
// reference to this C++ object.
[client_ invalidate];
}

- (void)invalidate {
[_displayLink invalidate];
_displayLink = nil; // Break retain cycle.
}

@knopp
Copy link
Member

knopp commented Jul 25, 2024

Another way to fix this: #54119

IOSSurfaceMetalImpeller::~IOSSurfaceMetalImpeller() = default;
IOSSurfaceMetalImpeller::~IOSSurfaceMetalImpeller() {
if ([layer_ isKindOfClass:[FlutterMetalLayer class]]) {
[(FlutterMetalLayer*)layer_.get() invalidate];
Copy link
Member

Choose a reason for hiding this comment

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

I have a preference for @knopp s patch. It really brittle for IOSSurfaceMetalImpeller to know to check if the layers is of a specific type to call a method on it.

@jonahwilliams
Copy link
Contributor Author

Let's do the other one

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants