GNOME Bugzilla – Bug 639660
Gio.MemoryInputStream.new_from_data aborts
Last modified: 2015-02-07 16:57:00 UTC
This: """ from gi.repository import Gio def destroy(data): pass Gio.MemoryInputStream.new_from_data("hi", -1, destroy) """ results in: ** ERROR:pygi-argument.c:981:_pygi_argument_from_object: code should not be reached
Do you have a backtrace of the abort?
+ Trace 225559
we don't support destroy notify callbacks without another callback (e.g. we assume GDestroyNotify as an aux parameter of callbacks). Is this useful to have in Python or should we just pass NULL? I'm not sure if this is possible since we marshal the data.
So, the 'data' argument will be a buffer that has been allocated by PyGObject from the PyString instance that your program is passing as the 'data' python argument. It makes no sense for your application to pass a destroy callback because your application hasn't allocated that buffer and doesn't know how to release it. It should be PyGObject who will decide which callback to pass and take care of releasing the memory referenced by the 'data' C argument. But, there's no way that PyGObject can get to know that, this information is only available by reading the docstrings or the glib code, so it's not consumable by PyGObject or the other introspection-enabled bindings. So I'm reassigning this bug to gobject-introspection in case we decide this kind of API should be introspectable and some information will be added to the typelib so bindings know what to do in this case. Otherwise, we could mark those functions as non-introspectable and add alternative API for bindings that would make a copy of the buffer and release it inside glib.
The only thing I can see us doing from the GI side is marking the user_data as being scoped for GDestroyNotify and only accepting data of specific types that we know we can safely free or unref. Otherwise Gio needs to provide an API that copies the data into its own internal buffer and frees it when it is no longer needed.
This now works but will leak due to the callback not managing the lifetime of the memory passed in: >>> from gi.repository import Gio >>> stream = Gio.MemoryInputStream.new_from_data(b'asdf') >>> outbytes = stream.read_bytes(4) >>> outbytes.get_data() b'asdf' Using new_from_bytes is a safer bet: >>> from gi.repository import GLib, Gio >>> inbytes = GLib.Bytes.new(b'asdf') >>> stream = Gio.MemoryInputStream.new_from_bytes(inbytes) >>> outbytes = stream.read_bytes(inbytes.get_size()) >>> outbytes.get_data() b'asdf' The GBytes construction is a bit painful so I've logged bug 729541.
[Mass-moving gobject-introspection tickets to its own Bugzilla product - see bug 708029. Mass-filter your bugmail for this message: introspection20150207 ]