GNOME Bugzilla – Bug 670216
Crash when calling pk_results_get_package_array()
Last modified: 2012-02-16 15:53:33 UTC
I'm attaching a test script that is crashing for me: it simply calls PackageKit to search for package, and while the resulting array is valid in the function that does the search, it becomes corrupted somehow after the function.
Created attachment 207772 [details] Small test
Output I get: ./test-pk.py MozillaFirefox [output 1] length=10 [output 1] 0: id=3053767732 [output 1] 0: obj=<Package object at 0xb604cc34 (PkPackage at 0x8151880)> [output 1] 1: id=3053767772 [output 1] 1: obj=<Package object at 0xb604cc5c (PkPackage at 0x81518f8)> [output 1] 2: id=3053767812 [output 1] 2: obj=<Package object at 0xb604cc84 (PkPackage at 0x8151970)> [output 1] 3: id=3053767852 [output 1] 3: obj=<Package object at 0xb604ccac (PkPackage at 0x81519e8)> [output 1] 4: id=3053767892 [output 1] 4: obj=<Package object at 0xb604ccd4 (PkPackage at 0x8151a60)> [output 1] 5: id=3053767932 [output 1] 5: obj=<Package object at 0xb604ccfc (PkPackage at 0x8151ad8)> [output 1] 6: id=3053767972 [output 1] 6: obj=<Package object at 0xb604cd24 (PkPackage at 0x8151b50)> [output 1] 7: id=3053768012 [output 1] 7: obj=<Package object at 0xb604cd4c (PkPackage at 0x8151c10)> [output 1] 8: id=3053768052 [output 1] 8: obj=<Package object at 0xb604cd74 (PkPackage at 0x8151c88)> [output 1] 9: id=3053768092 [output 1] 9: obj=<Package object at 0xb604cd9c (PkPackage at 0x8151d00)> [output 2] length=10 [output 2] 0: id=3053767732 Erreur de segmentation Stack trace: Program received signal SIGSEGV, Segmentation fault. pygobject_repr (self=0xb6903c34) at pygobject.c:1057 1057 pygobject.c: Aucun fichier ou dossier de ce type. in pygobject.c (gdb) bt
+ Trace 229679
If I remove the debug output, it doesn't crash, but I get many critical warnings like: GLib-GObject-CRITICAL **: g_object_unref: assertion `G_IS_OBJECT (object)' failed GLib-GObject-CRITICAL **: g_object_get_qdata: assertion `G_IS_OBJECT (object)' failed GLib-GObject-CRITICAL **: g_object_set_qdata_full: assertion `G_IS_OBJECT (object)' failed GLib-GObject-CRITICAL **: g_object_set_qdata_full: assertion `G_IS_OBJECT (object)' failed
I can reproduce on openSUSE Factory and Fedora 17 Alpha. Both come with pygobject 3.1.0 and PackageKit 0.7.2. It worked fine on a Fedora 16 VM I had (PackageKit 0.6.21 and pygobject 3.0.3).
I noticed that as well when I was working on it. I locally applied this to the PackageKit tree to avoid it: --- a/lib/packagekit-glib2/pk-results.c +++ b/lib/packagekit-glib2/pk-results.c @@ -536,7 +536,7 @@ pk_results_get_error_code (PkResults *results) * * Gets the packages from the transaction. * - * Return value: (element-type PkPackage) (transfer full): A #GPtrArray array of #PkPackage's, free with g_ptr_array_unref(). + * Return value: (element-type PkPackage) (transfer none): A #GPtrArray array of #PkPackage's, free with g_ptr_array_unref(). * * Since: 0.5.2 **/ But PK initializes the array with results->priv->package_array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); and pk_results_get_package_array() does return g_ptr_array_ref (results->priv->package_array); which does seem to indicate that (transfer none) would leak the array. I think (transfer full) is correct because it's _with_free_func(), and not just the container. Thus it looks like a problem with how pygobject handles pointer arrays.
However, (transfer container) seems to work. Maybe I misunderstand how ptrarrays work?
Works again when reverting http://git.gnome.org/browse/pygobject/commit/?id=c329bf2aee8d
For the record, Vincent and I discussed this: (transfer full) is correct wrt. how PK initializes, refs, and uses the array.
Actually, we both got it the wrong way around: with g_ptr_array_new_with_free_func(), the *array* owns the elements, so the caller only needs to do g_ptr_array_unref. This is what "transfer container" is for. With g_ptr_array_new(), the caller has to take care of unreffing the elements himself, i. e. the caller owns the elements instead of the array. This would be "transfer full". So this is a bug in PackageKit's annotations which got exposed by the recent leak fix in pygobject.
Fixed in https://gitorious.org/packagekit/packagekit/commit/046dd93cb65e7a3957ba6d6104cdb10c311c15fa
I committed a test to g-i/pygobject now which ensures that (transfer full) GPtrArrays work as well. Only indirectly related to this bug, of course, but it is better covered with a test.