After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 639660 - Gio.MemoryInputStream.new_from_data aborts
Gio.MemoryInputStream.new_from_data aborts
Status: RESOLVED FIXED
Product: gobject-introspection
Classification: Platform
Component: general
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gobject-introspection Maintainer(s)
gobject-introspection Maintainer(s)
Depends on:
Blocks: 625942
 
 
Reported: 2011-01-16 12:41 UTC by Jonathan Matthew
Modified: 2015-02-07 16:57 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Jonathan Matthew 2011-01-16 12:41:29 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
Comment 1 Bastien Nocera 2011-01-16 13:09:10 UTC
Do you have a backtrace of the abort?
Comment 2 Jonathan Matthew 2011-01-17 00:49:45 UTC


  • #0 raise
    from /lib64/libc.so.6
  • #1 abort
    from /lib64/libc.so.6
  • #2 g_assertion_message
    at gtestutils.c line 1358
  • #3 _pygi_argument_from_object
    at pygi-argument.c line 981
  • #4 _prepare_invocation_state
    at remote 0x812250>, 'hi', -1, <function at remote 0x7ffff7ed7230>)) at pygi-invoke.c line 500
  • #5 _wrap_g_function_info_invoke
    at remote 0x812250>, 'hi', -1, <function at remote 0x7ffff7ed7230>)) at pygi-invoke.c line 925
  • #6 ext_do_call
    at /usr/src/debug/Python-2.7/Python/ceval.c line 4381
  • #7 PyEval_EvalFrameEx
    at /usr/src/debug/Python-2.7/Python/ceval.c line 2760
  • #8 PyEval_EvalCodeEx

Comment 3 johnp 2011-01-17 09:23:06 UTC
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.
Comment 4 Tomeu Vizoso 2011-01-17 10:04:43 UTC
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.
Comment 5 johnp 2011-01-19 14:09:03 UTC
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.
Comment 6 Simon Feltman 2014-05-04 22:37:27 UTC
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.
Comment 7 André Klapper 2015-02-07 16:57:00 UTC
[Mass-moving gobject-introspection tickets to its own Bugzilla product - see bug 708029. Mass-filter your bugmail for this message: introspection20150207 ]