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
Memory leak when using events from subclass #165
Comments
One other thing, if you destroy the bEntry box in the delete button delegate after removing it things work as expected. I am doing this in terminix as well but forgot to include it in this reproducer. Having said that, this reproducer still shows how something can prevent D's GC from cleaning up objects. I'm hoping that maybe it can shed some light on my issue. |
I know whats going on. On the GTK+ side the objects are reference counted an on the GtkD side we use the GC. And there is some code in GtkD that makes sure the D object isn't collected if the reference GtkD has isn't the only one. When you create an object only GtkD has a reference to it, and the GC is free to collect it. But once you set an event handler, or add the widget to a container GTK+ also holds one or more references. And in that case the objects aren't collected so the handlers will keep working if the D code doesn't keep an reference to the object. For now you can call the |
Thanks @MikeWey, one follow-up question. In GTK the destroy is automatically propagated to the children however GTKD does not do this at it's level. I can see in the Widget.destroy all that is happening is the struct is being set to null, does this need to happen with all of child widgets for D's GC to clean them up? Like I said in Terminix I am calling destroy on the enclosing class (which is a Stack) that I remove but I'm still having the issue of the destructor never being called. I'm wondering if I should try explicitly calling destroy on the Terminal widget and/or the rest of the widget heirarchy? Having said that, it's quite possible I have a reference issue somewhere else that is eluding me. These memory issues are like whack-a-mole sometimes. |
In theory if you destroy a container like Stack it will decrease the reference count of all it's children by one. And if at that point GtkD holds the last reference the GC is free to destroy the object. |
Just to summarize the original problem, the vte has a finalizer that is cleaning up some file descriptors and @egmontkob noticed this wasn't happening in Terminix. I can see that I'm having an issue somewhere where either a D or GTK reference is being held onto which is preventing my high level Terminal Box, which adds the Terminal (VTE) widget, is not being GC'ed. As a workaround and test, I thought I'd simply try to removing the VTE widget directly, destroying it and setting the reference to null. From a D perspective, I can see that the D destructor is called however the VTE finalizer in GTK is not called. I quickly realized what the problem was, calling Widget.destroy() sets the struct to null, so that when ObjectG destructor is called it no longer has a reference to the struct and can't unref it. Thus the finalizer never actually gets called. The solution is to comment out the setStruct(null) in Widget.d:
Once this is done, the VTE finalizer is called as expected. I'm not sure why the struct is being set to null there, maybe this setting it to null should be moved to the ObjectG destructor? |
The But it seems that I'll try and see if this is really whats causing the problems. |
Just passing by and saw this, just a clarification: |
That looks to be the case, judging by the code. Although the documentation states:
So it might be destroyed but not finalized. |
oh right |
@MikeWey I fixed the original issue that sparked this, the two issues that remain on your side are as follows:
|
Btw, I'm not sure how big a deal point 1 is, I managed to work around the issue of calling destroy on VTE preventing finalization. However there are a few spots where I've had to explicitly call destroy on other gtk widgets. Not sure how prevalent finalization is in the gtk outside of VTE. |
Hey Gerald, if I understood correctly your question... gtk finalization is "mandatory", as any other GObject, so every gtk widget must free its resources in there. |
I've added a unref call in de destroy callback. |
Thanks @MikeWey, much appreciated. |
Below is a simple reproducer for a problem I'm having in Terminix (gnunn1/tilix#589) where objects don't seem to be released properly when using eventHandlers. I'm not sure if this is a GtkD problem, an issue with D's GC not handling chained dependencies or a coding practice I shouldn't be doing.
When you run the reproducer, it has an Add and Delete button. Clicking the Add Button creates a new Box with an Entry, clicking the Delete button removes and calls the D GC to collect (just to force things for testing purposes). The CustomVox and CustomEntry which are created have destructors that simply write a line out to stdout.
If you run the code and press Add then Delete and repeat several times you will see that the destructors for CustomBox and CustomEntry are not being executed. However, if you comment out the line:
and repeat the test you will see that the destructors are being called properly.
My expectation is that because the CustomBox is not being referenced in D anywhere that it should be GC'ed, however something with the event handler between the CustomBox and CustomEvent is stopping it from working. Is this incrementing the reference count and preventing the GC from removing the struct from root maybe?
The text was updated successfully, but these errors were encountered: