mvz / gir_ffi

Auto-generate bindings for GObject based libraries at run time using FFI
https://github.com/mvz/gir_ffi/wiki
GNU Lesser General Public License v2.1
144 stars 14 forks source link

Object property reference leak #82

Open kugel- opened 7 years ago

kugel- commented 7 years ago

I'm trying to create an instance of a GObject-derived type (defined in Ruby) in C code. If that type has a property of type GObject (i..e reference counted) the reference seems to leak after freeing the type. To be clear, references to the property object are leaking, not the reference to the object that has the property.

Here's a small program that reproduces the problem:

https://gist.github.com/kugel-/0b051d9a22516ea53b48d33009d11175

mvz commented 7 years ago

GirFFI is not really intended to be used in this way: The set up of finalizers probably isn't triggered if you intantiate the object from C.

mvz commented 7 years ago

Incidentally, can you get this to work with Ruby-GNOME2?

kugel- commented 7 years ago

ruby-gnome2 doesn't support interfaces at this time. My focus went to GirFFI after I found that (although I was able to bring interface support with a quick hack).

Regarding the leak: I don't think it's related finalization at all. I can see that in value.rb, Value#get_value (via set_instance_enhanced) increments the ref_count (when assigning a gobject property). But that is never decremented again. The finalizer just decrements the ref count of the container object which does by itself not unref properties. IMO Value#get_value should not increment the ref_count, why is this done?

Regarding the setup of finalizers (this issue is orthogonal) I experimented a bit, there are two possible ways: 1) There are more class methods we can attach to, e.g. GObjectClass->constructed and GObjectClass->dispose(). Using these we can hook into the construction/destruction even if native code does g_object_new() Especially constructed seems useful as it allows to get rid of predefining initialize on the Ruby side. What do you think?

2) I can setup this so that the instance is created with Ruby but that complicates passing construct properties.

PS: For I'm struggling wih #63 which is a show-stopper for my project (libpeas support for ruby)

mvz commented 7 years ago

Value#get_value needs to increment the ref_count because it creates a new Ruby object that needs to have ownership of the GObject object, while at the same time it needs to hold on to its own reference.

mvz commented 7 years ago

However, I don't think any of the Ruby implementation of Value is called in your example. I'm investigating further to see what's happening exactly.

kugel- commented 7 years ago

It is, I tracked it. set_instance_enhanced is called for the object property.

gobjects aren't ref'd by default when it is assigned to a property. Maybe here's some confusion?

mvz commented 7 years ago

Ah yes, #get_value is in fact called in the setter.

The only solution I can see is for me to extend the finalizer for Value to also lower the reference count of any object it holds.

mvz commented 7 years ago

By the way, do you have an example of what currently doesn't work in ruby-gnome2?

kugel- commented 7 years ago

ruby-gnome2 doesn't setup vfuncs when implementing an interface. in fact it doesn't handle include MyInterface at all yet. I have a quick hack to add that but it needs more work to be acceptable.