GNOME Bugzilla – Bug 656314
wnck_screen_get_default() segfaults when using introspection - need to import all dependencies
Last modified: 2015-10-26 08:44:17 UTC
Created attachment 193603 [details] stacktrace $ python >>> import wnck >>> wnck.screen_get_default() <wnck.Screen object at 0x27d8460 (WnckScreen at 0x281c010)> ~~~~~~~~~~~ $ python >>> from gi.repository import Wnck >>> Wnck.Screen.get_default() (process:20645): Gdk-CRITICAL **: gdk_x11_display_get_xdisplay: assertion `GDK_IS_DISPLAY (display)' failed Segmentation fault I can reproduce this reliably on two Fedora 16 (branched) boxes. Apologies if this is a downstream/unstable-release thing....
This is probably a missing/incorrect transfer annotation for wnck_screen_get_default().
So after some help in #python, the conclusion seems to be that the bug is a big ol' case of user (reporter) fail: < tomeu> Internally, libwnck uses GDK. This means that before any call to libwnck API, GDK needs to be initialized. This can be achieved with gdk_init(), or indirectly via gtk_init(). < tomeu> joanie: I think just importing Gdk would do it < joanie> k I'll try < joanie> oh man < joanie> lol < joanie> that works < tomeu> \o/ Sorry! (And thanks guys!!)
< jdahlin> joanie: it's a bug, Gdk.init() shouldn't be needed, perhaps the Gdk override should call it automatically < joanie> jdahlin: would you like me to reopen the bug? < jdahlin> joanie: sure, I think it represents a valid problem Reopening and moving to pygobject.
So Gdk does already do the init. The problem is you need to import Gdk for the overrides to load. Perhaps we should iterate through all the gir's dependency's and import those modules.
Indeed, this works: >>> from gi.repository import Gdk, Wnck >>> Wnck.Screen.get_default() <Screen object at 0x7f6a91f9ce60 (WnckScreen at 0x15df830)> It's not related to the overrides (the exact same problem/fix also works without Gdk overrides), we just need to take care of importing dependencies.
*** Bug 673396 has been marked as a duplicate of this bug. ***
*** Bug 698005 has been marked as a duplicate of this bug. ***
As it's mentioned in bug 698005, from gi.repository import Gtk, GdkX11 might help.
Created attachment 284916 [details] [review] Add private gi._gi.Repository.get_dependencies() method to Python Add static wrapper for g_irepository_get_dependencies() for usage with auto-loading dependent typelibs.
Created attachment 284917 [details] [review] Import dependencies when importing typelibs from gi.repository Recursively import a modules dependencies when importing from gi.repsository.
Slightly concerned over performance implications of the patches. We need to test load times before and after and either commit this or mark the bug as won't fix depending on the outcome after the 3.14 release.
Not sure why, but importing "from gi.repository import GLib, GObject, Atk, GdkPixbuf, Gio, Pango, cairo, Gdk, xlib, Gtk" is 30% faster here than just "from gi.repository import Gtk" the important things seems to be that Gdk is imported before Gtk. Any idea why that could be?
Created attachment 312621 [details] [review] Import dependencies when importing typelibs from gi.repository Recursively import a modules dependencies when importing from gi.repository. This fixes the case where a library depends on initialization code of dependency overrides. For example libwnck expects gdk_init to be called before using its API and gdk_init gets called in the Gdk overrrides.
(In reply to Martin Pitt from comment #5) > Indeed, this works: > > >>> from gi.repository import Gdk, Wnck > >>> Wnck.Screen.get_default() > <Screen object at 0x7f6a91f9ce60 (WnckScreen at 0x15df830)> > > It's not related to the overrides (the exact same problem/fix also works > without Gdk overrides), we just need to take care of importing dependencies. I can't reproduce this. libwnck segfaults because gdk_display_get_default returns NULL which is fixed by calling gdk_init() in the overrides. (In reply to Christoph Reiter (lazka) from comment #12) > Not sure why, but importing > > "from gi.repository import GLib, GObject, Atk, GdkPixbuf, Gio, Pango, cairo, > Gdk, xlib, Gtk" > > is 30% faster here than just > > "from gi.repository import Gtk" > > the important things seems to be that Gdk is imported before Gtk. Any idea > why that could be? Turns out that calling gdk_init()+gtk_init() is 40ms faster than just calling gtk_init() alone. Including a construction of a GtkWidget the time spend is the same again, so I suspect some lazy loading differences. Needs investigating (faster import would be nice, even if the work just gets shifted elsewhere) ------ Regarding the above updated patch: * It uses the new get_immediate_dependencies() as get_dependencies behavior was changed in recent libgirepository. * It uses is_registered() as a fast path to check if a namespace is available on import which saves 5ms when importing lots of dependencies. Performance impact: * "from gi.repository import Gdk, Gtk" ~4ms slower * "from gi.repository import Gdk, Gtk, ClutterGdk" ~5ms slower ClutterGdk has ~20 dependencies, so all in all it doesn't seem too bad.
(In reply to Christoph Reiter (lazka) from comment #14) > Turns out that calling gdk_init()+gtk_init() is 40ms faster than just > calling gtk_init() alone. Including a construction of a GtkWidget the time > spend is the same again, so I suspect some lazy loading differences. Needs > investigating (faster import would be nice, even if the work just gets > shifted elsewhere) This turned out to be bug 756147 which is now fixed in gtk+ trunk.
Review of attachment 312621 [details] [review]: LGTM, thanks.
Thanks. https://git.gnome.org/browse/pygobject/commit/?id=dba1da9b0770c7dec1abd82303b9b4266fe2ce3f