Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ios] fix memory leak in Frame, VisualElementRenderer #18552

Merged

Conversation

jonathanpeppers
Copy link
Member

Context: #18365

I could reproduce a leak in Frame by adding a parameterized test:

[InlineData(typeof(Frame))]
public async Task HandlerDoesNotLeak(Type type)

FrameRenderer has a circular reference via its base type, VisualElementRenderer:

  • Frame ->
  • FrameRenderer / VisualElementRenderer ->
  • Frame (via VisualElementRenderer._virtualView)

To solve this issue, I made _virtualView a WeakReference, but only on iOS or MacCatalyst platforms. We don't necessarily need this treatment for Windows or Android.

My initial attempt threw a NullReferenceException, because the Element property is accessed before SetVirtualView() returns. I had to create a _tempElement field to hold the value temporarily, clearing it to avoid a circular reference.

The Roslyn analyzer didn't catch this cycle because it doesn't warn about IPlatformViewHandler, only NSObject's. Will investigate further on this example here:

jonathanpeppers/memory-analyzers#12

Context: dotnet#18365

I could reproduce a leak in `Frame` by adding a parameterized test:

    [InlineData(typeof(Frame))]
    public async Task HandlerDoesNotLeak(Type type)

`FrameRenderer` has a circular reference via its base type,
`VisualElementRenderer`:

* `Frame` ->
* `FrameRenderer` / `VisualElementRenderer` ->
* `Frame` (via `VisualElementRenderer._virtualView`)

To solve this issue, I made `_virtualView` a `WeakReference`, but only
on iOS or MacCatalyst platforms. We don't necessarily need this
treatment for Windows or Android.

My initial attempt threw a `NullReferenceException`, because the
`Element` property is accessed before `SetVirtualView()` returns. I
had to create a `_tempElement` field to hold the value temporarily,
clearing it to avoid a circular reference.

The Roslyn analyzer didn't catch this cycle because it doesn't warn
about `IPlatformViewHandler`, only `NSObject`'s. Will investigate
further on this example here:

jonathanpeppers/memory-analyzers#12
@jonathanpeppers jonathanpeppers added this to the .NET 8 + Servicing milestone Nov 6, 2023
@jonathanpeppers jonathanpeppers marked this pull request as ready for review November 7, 2023 02:57
@jonathanpeppers jonathanpeppers requested a review from a team as a code owner November 7, 2023 02:57
@jonathanpeppers jonathanpeppers added memory-leak 💦 Memory usage grows / objects live forever (sub: perf) platform/iOS 🍎 labels Nov 7, 2023
@Eilon Eilon added the legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor label Nov 9, 2023
@jonathanpeppers jonathanpeppers merged commit 8bc2a2f into dotnet:main Nov 13, 2023
@jonathanpeppers jonathanpeppers deleted the VisualElementRendererLeaks branch November 13, 2023 19:58
@github-actions github-actions bot locked and limited conversation to collaborators Dec 14, 2023
@Eilon Eilon added area-controls-frame Frame and removed legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor labels May 13, 2024
@samhouts samhouts added the fixed-in-8.0.6 Look for this fix in 8.0.6 SR1! label Aug 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-controls-frame Frame fixed-in-8.0.6 Look for this fix in 8.0.6 SR1! memory-leak 💦 Memory usage grows / objects live forever (sub: perf) platform/iOS 🍎
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants