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 666270 - Support GHashTable and GError as closure arguments
Support GHashTable and GError as closure arguments
Status: RESOLVED FIXED
Product: pygobject
Classification: Bindings
Component: introspection
Git master
Other Linux
: Normal normal
: ---
Assigned To: Nobody's working on this now (help wanted and appreciated)
Python bindings maintainers
Depends on:
Blocks:
 
 
Reported: 2011-12-15 14:11 UTC by Mardy
Modified: 2012-01-30 15:10 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Proposed fix (1013 bytes, patch)
2011-12-15 14:16 UTC, Mardy
none Details | Review
Add regress test methods for callbacks taking GError and GHashTable (5.98 KB, patch)
2012-01-23 08:39 UTC, Martin Pitt
none Details | Review
Add test cases for callbacks taking GError/GHashTable (1.89 KB, patch)
2012-01-23 08:50 UTC, Martin Pitt
none Details | Review
Add regress test methods for callbacks taking GError and GHashTable (5.96 KB, patch)
2012-01-23 09:05 UTC, Martin Pitt
none Details | Review
Add regress test methods for callbacks taking GError and GHashTable (5.97 KB, patch)
2012-01-23 10:42 UTC, Martin Pitt
none Details | Review
Second patch for gobject-introspection (3.53 KB, patch)
2012-01-23 11:13 UTC, Mardy
needs-work Details | Review
pygobject: fix indentation (1.59 KB, patch)
2012-01-23 11:16 UTC, Mardy
committed Details | Review
pygobject: respect transfer type when demarshalling GErrors (1.37 KB, patch)
2012-01-23 11:17 UTC, Mardy
none Details | Review
pygobject: second test case for GError: transfer full (1.28 KB, patch)
2012-01-23 11:18 UTC, Mardy
none Details | Review
gobject-introspection: second patch, for transferred GErrors (4.11 KB, patch)
2012-01-23 12:36 UTC, Mardy
none Details | Review
[g-i] Add regress test methods for callbacks taking GError and GHashTable (7.97 KB, patch)
2012-01-23 13:56 UTC, Martin Pitt
committed Details | Review
[1/1] Support GHashTable and GError as callback/closure arguments (3.10 KB, patch)
2012-01-23 14:09 UTC, Martin Pitt
committed Details | Review
[2/2] Respect transfer-type when demarshalling GErrors (1.64 KB, patch)
2012-01-23 14:10 UTC, Martin Pitt
committed Details | Review

Description Mardy 2011-12-15 14:11:42 UTC
In the library which I want to use from python [0] there's the following callback definition:

typedef void (*SignonAuthSessionProcessCb) (SignonAuthSession *self,     
                                            GHashTable *session_data,    
                                            const GError *error,         
                                            gpointer user_data);         

In my python code, this asynchronous callback is successfully invoked, but the "session_data" and "error" parameters are always "None". After some debugging, I found that the marshalling of GHashTable and GError in pygi-closure.c is not handled (variables of these types are always set to NULL).


[0] http://code.google.com/p/accounts-sso/source/browse/?repo=libsignon-glib
Comment 1 Mardy 2011-12-15 14:16:55 UTC
Created attachment 203577 [details] [review]
Proposed fix

Marshalling of GHashTable and GError from C to python is already implemented; the attached patch trivially brings it into use for closures too.

I tested this with the before mentioned library and it works nicely, both for GHashTable and GError.
Comment 2 Martin Pitt 2012-01-20 14:47:50 UTC
Thanks for this! This should go along with a test case, though, to ensure that it works and stays working.
Comment 3 Martin Pitt 2012-01-23 08:39:33 UTC
Created attachment 205852 [details] [review]
Add regress test methods for callbacks taking GError and GHashTable

It seems this simple patch isn't sufficient. I created some regression tests around this, and it seems to have quite some problems. As I don't know any details about how you use these callbacks in your code, I just created two very simple test functions which just take a callback which take a GError, or a GHashTable respectively.

This is the patch to gobject-introspection which adds the two new test functions.
Comment 4 Martin Pitt 2012-01-23 08:50:05 UTC
Created attachment 205853 [details] [review]
Add test cases for callbacks taking GError/GHashTable

This adds pygobject test cases for calling the two new Regress functions (from the previous g-i patch).

Without your patch, the arguments indeed are None, as you said:

testCallbackGError (test_everything.TestCallbacks) ... Traceback (most recent call last):
  • File "/home/martin/upstream/pygobject/tests/test_everything.py", line 358 in callback
    self.assertEqual(error.message, 'regression test error')
AttributeError: 'NoneType' object has no attribute 'message'
FAIL
[...]
testCallbackHashTable (test_everything.TestCallbacks) ... Traceback (most recent call last):
[...]
AssertionError: None != {'foo': 1, 'bar': 2}

and the two cases fail on "self.assertTrue(TestCallbacks.called)" as the callbacks error out before setting called = True.

With your simple patch, however, it doesn't look much better. The GError one callback fails with

  File "/home/martin/upstream/pygobject/tests/test_everything.py", line 360, in callback
    self.assertEqual(error.code, Gio.IOErrorEnum.NOT_SUPPORTED)
  [...]
  AssertionError: 0 != <enum G_IO_ERROR_NOT_SUPPORTED of type GIOErrorEnum>
FAIL

i. e. the error.code field is not valid (error.domain and error.message seem to be correct). On top of that, it seems to cause memory corruption, as one of the following test cases segfaults:

  testCallbackUserdataRefCount (test_everything.TestCallbacks) ... make[2]: *** [check-local] Segmentation fault (core dumped)

When I comment out the g_error_free() in regress_test_gerror_callback() in the g-i patch, the segfault doesn't happen. So this might interact badly with some pygobject magic handling of GErrors, or is just due to the too simple handling of the GError object in your _pygi_closure_convert_ffi_arguments() patch?


The GHashTable test callback gets a bogus dictionary passed:

testCallbackHashTable (test_everything.TestCallbacks) ... Traceback (most recent call last):
  File "/home/martin/upstream/pygobject/tests/test_everything.py", line 369, in callback
    self.assertEqual(data, mydict)
  [...]
  AssertionError: {'\x0b': 40728480, '\n': 40728504} != {'foo': 1, 'bar': 2}
  - {'\n': 40728504, '\x0b': 40728480}
  + {'bar': 2, 'foo': 1}

and modifying it doesn't work of course.

So I don't think we can apply this until this works.

Does that patch actually work for you? Perhaps you can add some more context what and how you call?
Comment 5 Martin Pitt 2012-01-23 09:05:01 UTC
Created attachment 205854 [details] [review]
Add regress test methods for callbacks taking GError and GHashTable

I forgot to annotate the GHashTable data types in test_hash_table_callback() as well (just did it in the TestCallbackHashtable type). With that, the GHashTable test works fine now.

So that leaves the GError problems: the invalid code and the crash.
Comment 6 Martin Pitt 2012-01-23 10:42:57 UTC
Created attachment 205860 [details] [review]
Add regress test methods for callbacks taking GError and GHashTable

Actually throw G_IO_ERROR_NOT_SUPPORTED instead of G_IO_ERROR_FAILED in the g-i regression test functions. For the purpose of a test case, it's better to use an error code which is not actually zero. Now the pygobject testCallbackGError case actually works, it just causes the segfault.

The segfault happens because pygobject ignores the "(transfer none)" annotation for GError, and thus the resulting double free causes a segfault. I guess the marshaller should use a separate case: for GError and use g_error_copy() for this?
Comment 7 Martin Pitt 2012-01-23 10:44:04 UTC
Comment on attachment 205853 [details] [review]
Add test cases for callbacks taking GError/GHashTable

Argh, obsoleted the wrong attachment..
Comment 8 Christian Fredrik Kalager Schaller 2012-01-23 11:12:13 UTC
Seems to be some overlap between this bug (and patches) and https://bugzilla.gnome.org/show_bug.cgi?id=666098 and the patches in that bug
Comment 9 Mardy 2012-01-23 11:13:59 UTC
Created attachment 205865 [details] [review]
Second patch for gobject-introspection

gobject-introspection patch to add another method for regression tests; similar to the above, but in this case the GError transfer is "full".
Comment 10 Mardy 2012-01-23 11:16:44 UTC
Created attachment 205866 [details] [review]
pygobject: fix indentation
Comment 11 Mardy 2012-01-23 11:17:31 UTC
Created attachment 205867 [details] [review]
pygobject: respect transfer type when demarshalling GErrors
Comment 12 Mardy 2012-01-23 11:18:47 UTC
Created attachment 205868 [details] [review]
pygobject: second test case for GError: transfer full

Now all patches are uploaded.
Comment 13 Martin Pitt 2012-01-23 11:21:06 UTC
Comment on attachment 205866 [details] [review]
pygobject: fix indentation

Indentation patch is trivial, pushed this.
Comment 14 Martin Pitt 2012-01-23 11:44:20 UTC
Comment on attachment 205865 [details] [review]
Second patch for gobject-introspection

The second g-i patch is missing the actual definition of TestCallbackOwnedGError.

Please run make check in g-i, to see this. The test fails because TestCallbackOwnedGError is missing in the gir, and test_owned_gerror_callback() is generated on a different position.
Comment 15 Martin Pitt 2012-01-23 11:45:03 UTC
Comment on attachment 203577 [details] [review]
Proposed fix

Removing "needs work" from original patch, as the second pygobject patch fixes the transfer ownership handling for GError.
Comment 16 Mardy 2012-01-23 12:36:27 UTC
Created attachment 205874 [details] [review]
gobject-introspection: second patch, for transferred GErrors

(In reply to comment #14)
> (From update of attachment 205865 [details] [review])
> The second g-i patch is missing the actual definition of
> TestCallbackOwnedGError.

Fixed.
Comment 17 Martin Pitt 2012-01-23 13:55:55 UTC
Thanks Mardy! These patches look fine to me, and they are working nicely now. The second g-i one is missing a "transfer full" annotation for the TestCallbackOwnedGError type (as that's what we are intend to test).

For final upstream committing they ought to get merged (at least the two parts for the test cases).
Comment 18 Martin Pitt 2012-01-23 13:56:53 UTC
Created attachment 205879 [details] [review]
[g-i] Add regress test methods for callbacks taking GError and GHashTable

This merges the two g-i patches to add the three Regress functions and fixes the annotation.
Comment 19 Martin Pitt 2012-01-23 14:09:50 UTC
Created attachment 205882 [details] [review]
[1/1] Support GHashTable and GError as callback/closure arguments

This pygobject patch consolidates the first patch and the two test case patches and removes an unused variable in the new test cases, and now also has a consistent commit log.
Comment 20 Martin Pitt 2012-01-23 14:10:50 UTC
Created attachment 205883 [details] [review]
[2/2] Respect transfer-type when demarshalling GErrors

This second patch just updates the commit log for the "transfer full" patch.
Comment 21 Martin Pitt 2012-01-25 05:56:00 UTC
Thanks Tomeu for the review!
Comment 22 Christian Fredrik Kalager Schaller 2012-01-30 12:40:34 UTC
Hi Martin and Mardy,
I think this crash I am seeing might be caused by your patches:
https://bugzilla.gnome.org/show_bug.cgi?id=669018
Comment 23 Mardy 2012-01-30 12:59:51 UTC
Hi Christian, that's seems related indeed. If you don't want python-gobject to free the GError, you need to set the "transfer none" annotation on the signal.
Comment 24 Christian Fredrik Kalager Schaller 2012-01-30 13:40:50 UTC
Thanks Mardy, 

For posterity, the correct link for 22 is : 
https://bugzilla.gnome.org/show_bug.cgi?id=668862 

which is the actual bug report for the crasher.
Comment 25 Martin Pitt 2012-01-30 15:10:45 UTC
I subscribed to bug 668862 now and asked a question there. Thanks for the pointer.