Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.

[GTK] Fix several memory leaks in the GTK backend#4112

Merged
PureWeen merged 4 commits intoxamarin:masterfrom
fluendo:gtk-mem-leaks
Oct 30, 2018
Merged

[GTK] Fix several memory leaks in the GTK backend#4112
PureWeen merged 4 commits intoxamarin:masterfrom
fluendo:gtk-mem-leaks

Conversation

@ylatuya
Copy link
Copy Markdown
Contributor

@ylatuya ylatuya commented Oct 17, 2018

Description of Change

This serie of patches fixes several memory leaks in the GTK backend.
The first one is the MasterDetailPage that is not cleaning up old pages when the Detail or Menu page is changed.

Another issue is how disposal of Gtk objects is handled, wich is now incorrectly done using the Dispose function. Gtk objects should be disposed using the Destroy function that will automatically iterate over the children and destroy them too (https://developer.gnome.org/gtk2/stable/GtkWidget.html#gtk-widget-destroy).

The gtk-sharp bindings discourage the use of Dispose and don't even call the base class, leaving it without effect (https://github.com/mono/gtk-sharp/blob/gtk-sharp-2-12-branch/gtk/Object.custom#L98), so that's why Gtk objects should override the Destroy function. Problably the gtk-sharp bindings should be changed at some point to have a more idiomatic pattern for disposal, but that would break backwards compatibility, so right now the only possible solution is to use Destroy.

I created a demo application with a MaterDetail that calls the GC on each Detail change. As you can see the number of live objects in master keeps growing while in this branch it's mostly steady going up and down.

Before
screen shot 2018-10-17 at 11 26 54

After
screen shot 2018-10-17 at 11 25 13

Issues Resolved

API Changes

None

Platforms Affected

  • Gtk

Behavioral/Visual Changes

None

Before/After Screenshots

Not applicable

Testing Procedure

Create a sample MasterDetail application with 2 pages and some content inside the pages.
Call a full garbage collection after switching pages that also waits for pending finalizers.
Launch the application in the profiler with automatic snapshots on garbage collection.

PR Checklist

  • Has automated tests
  • Rebased on top of the target branch at time of PR
  • Changes adhere to coding standard

@rmarinho
Copy link
Copy Markdown
Member

needs rebase ?

@ylatuya
Copy link
Copy Markdown
Contributor Author

ylatuya commented Oct 17, 2018

I pushed the wrong branch, everything should be fine now.

@PureWeen PureWeen requested review from PureWeen and hartez October 17, 2018 13:53
@ylatuya ylatuya changed the title Fix several memory leaks in the GTK backend [GTK] Fix several memory leaks in the GTK backend Oct 17, 2018
@samhouts samhouts added the p/gtk label Oct 17, 2018
@ylatuya
Copy link
Copy Markdown
Contributor Author

ylatuya commented Oct 17, 2018

Regarding the MasterDetailPage leak, I am not so sure if the solution is the correct one. Should the MasterDetailPage be responsible of disposing the old Detail or should the application be responsible of doing so? I am think of scenarios in which the application would want to reuse the Page and just switch them using the Detail property.

@ylatuya
Copy link
Copy Markdown
Contributor Author

ylatuya commented Oct 17, 2018

I just removed the disposal of the Detail page from the MasterDetailPage since it shouldn't be it's responsibility, but now any page set as Detail in the MasterDetailPage is leaked.

Copy link
Copy Markdown
Contributor

@jsuarezruiz jsuarezruiz left a comment

Choose a reason for hiding this comment

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

Tested. Checking the list of controls inside the Controls folder, there are several ones (SearchEntry, OpenGLView, etc) where Destroy could be used although we can leave it for another PR.

@ylatuya
Copy link
Copy Markdown
Contributor Author

ylatuya commented Oct 21, 2018

I will check that because I thought I fixed all of them. There are two different scenarios, Controls using Gtk elements directly, where you have to use Destroy, and those inheriting from ViewRenderer where the base class handles it and you can have a more idiomatic implementation using Dispose

@ylatuya
Copy link
Copy Markdown
Contributor Author

ylatuya commented Oct 22, 2018

@jsuarezruiz Looking that reset of components, SearchEntry is using Destroy with the changes in this PR, GLWidget was already using Destroy, so everything should beok

public class MasterDetailPageRenderer : AbstractPageRenderer<Controls.MasterDetailPage, MasterDetailPage>
{
Page currentMaster;
Page currentDetail;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Prefix these two with _

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

@PureWeen
Copy link
Copy Markdown
Contributor

@ylatuya can you rebase this to master? There were some errors that got checked into master a while ago and your branch doesn't have the fix so the build is currently failing with

Xamarin.Forms.Controls.Issues\Xamarin.Forms.Controls.Issues.Shared\Issue3979.xaml.cs(32,4): Error CS0103: The name 'TargetSpan' does not exist in the current context
Xamarin.Forms.Controls.Issues\Xamarin.Forms.Controls.Issues.Shared\Issue3979.xaml.cs(32,4): Error CS0103: The name 'TargetSpan' does not exist in the current context
Xamarin.Forms.Controls.Issues\Xamarin.Forms.Controls.Issues.Shared\Issue3979.xaml.cs(32,4): Error CS0103: The name 'TargetSpan' does not exist in the current context
Xamarin.Forms.Controls.Issues\Xamarin.Forms.Controls.Issues.Shared\Issue3979.xaml.cs(32,4): Error CS0103: The name 'TargetSpan' does not exist in the current context
Process 'msbuild.exe' exited with code '1'.

Gtk objects must be disposed using the Destroy function that will
automatically iterate over the children and destroy them too:
https://developer.gnome.org/gtk2/stable/GtkWidget.html#gtk-widget-destroy

The gtk-sharp bindings discourage the use of Dispose and don't even call
the base class, leaving it without effect:
https://github.com/mono/gtk-sharp/blob/gtk-sharp-2-12-branch/gtk/Object.custom#L98

In the Controls, that inherits directly from native Gtk objects, the
overrides of the Dispose function are changed to override the Destroy
function.  In the Renderers, that inherit from VisualElementRenderer,
the Destroy funtion is called in the dispose implementation so
subclasses only have to override Dispose (bool disposing) as they do
now.
@ylatuya
Copy link
Copy Markdown
Contributor Author

ylatuya commented Oct 27, 2018

Rebased and comments processed

@PureWeen
Copy link
Copy Markdown
Contributor

build

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.

6 participants