mvz / gir_ffi

Auto-generate bindings for GObject based libraries at run time using FFI

Home Page:https://github.com/mvz/gir_ffi/wiki

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

finalizing a GValue does not seem to call g_value_unset()

jcupitt opened this issue · comments

Hi, I think I've found a reference-counting problem and a clear explanation.

If some C code sets a GValue to an object with g_value_set_object (), the value will hold a reference to the object, see:

https://developer.gnome.org/gobject/stable/gobject-Standard-Parameter-and-Value-Types.html#g-value-get-object

Therefore when that GValue is finalized, the reference must be dropped. This happens automatically when you call g_value_unset(), see:

https://developer.gnome.org/gobject/stable/gobject-Generic-values.html#g-value-unset

This does not seem to happen, for example:

irb(main):001:0> require 'gir_ffi'
irb(main):002:0> GirFFI.setup :Vips
irb(main):003:0> Vips::init($PROGRAM_NAME)
irb(main):004:0> op = Vips::Operation.new "jpegload"
irb(main):005:0> op.set_property "filename", "/home/john/pics/k2.jpg"
irb(main):006:0> result = op.build

After setup, we have two objects: an operation and an image. The op we have built above, the image is held as a property of the op. The image has a single floating reference, and in turn holds a ref to the object.

You can see the counts with:

irb(main):007:0> Vips::Object::print_all
2 objects alive:
0) VipsForeignLoadJpegFile (0x24f5030), count=2
1) VipsImage (0x25a1010) 1080 bytes, count=1

Now we fetch the image property. The get_property method on op will use g_value_set_object() to set the GValue to the image, adding another count:

irb(main):008:0> out = op.property("out")
=> #<GObject::Value:0x000000025c4570 @struct=#<GObject::Value::Struct:0x000000025c4548>>
irb(main):009:0> Vips::Object::print_all
2 objects alive:
0) VipsForeignLoadJpegFile (0x24f5030), count=2
1) VipsImage (0x25a1010) 1080 bytes, count=2

Now finalizing the GValue should call g_value_unset() and drop the ref, but it does not seem to do this:

irb(main):012:0> out = nil
irb(main):013:0> GC.start
irb(main):014:0> Vips::Object::print_all
2 objects alive:
0) VipsForeignLoadJpegFile (0x24f5030), count=2
1) VipsImage (0x25a1010) 1080 bytes, count=2

The counts are unchanged. I couldn't see a call to unset, though maybe I missed it:

john@bambam ~/GIT/gir_ffi (master) $ find . -name "*.rb" -exec grep -l unset {} \;
./test/integration/generated_regress_test.rb

This is with git master gir_ffi.

@jcupitt thanks for your detailed bug report. I'll look into it.

Fixed in master.