GNOME Bugzilla – Bug 563823
segfault with invalid $DISPLAY
Last modified: 2018-08-17 13:34:39 UTC
[ Original report: http://bugs.debian.org/505832 from Timo Juhani Lindfors ] Steps to reproduce: 1) cat > prog.py <<EOF import gobject import pygtk import gtk loop = gobject.MainLoop() w = gtk.Window(gtk.WINDOW_TOPLEVEL) w.set_default_size(480, 300) w.show() vbox = gtk.VBox(False, 0) w.add(vbox) vbox.show() loop.run() EOF 2) DISPLAY=:99 python prog.py Expected results: 2) python-gtk complains about not being able to connect to DISPLAY :99 Actual results: 2) python-gtk prints a lot of warnings and then segfaults: /var/lib/python-support/python2.5/gtk-2.0/gtk/__init__.py:72: GtkWarning: could not open display warnings.warn(str(e), _gtk.Warning) prog.py:6: Warning: invalid (NULL) pointer instance w = gtk.Window(gtk.WINDOW_TOPLEVEL) prog.py:6: Warning: g_signal_connect_data: assertion `G_TYPE_CHECK_INSTANCE (instance)' failed w = gtk.Window(gtk.WINDOW_TOPLEVEL) prog.py:8: GtkWarning: Screen for GtkWindow not set; you must always set a screen for a GtkWindow before using the window w.show() prog.py:8: GtkWarning: gdk_screen_get_default_colormap: assertion `GDK_IS_SCREEN (screen)' failed w.show() prog.py:8: GtkWarning: gdk_colormap_get_visual: assertion `GDK_IS_COLORMAP (colormap)' failed w.show() prog.py:8: GtkWarning: gdk_screen_get_root_window: assertion `GDK_IS_SCREEN (screen)' failed w.show() prog.py:8: GtkWarning: _gdk_window_new: assertion `GDK_IS_WINDOW (parent)' failed w.show() prog.py:8: GtkWarning: gdk_window_enable_synchronized_configure: assertion `GDK_IS_WINDOW (window)' failed w.show() prog.py:8: GtkWarning: gdk_window_set_user_data: assertion `window != NULL' failed w.show() prog.py:8: GtkWarning: gtk_style_attach: assertion `window != NULL' failed w.show() prog.py:8: GtkWarning: gtk_style_set_background: assertion `GTK_IS_STYLE (style)' failed w.show() prog.py:8: GtkWarning: gtk_paint_flat_box: assertion `GTK_IS_STYLE (style)' failed w.show() prog.py:8: GtkWarning: gdk_window_set_accept_focus: assertion `GDK_IS_WINDOW (window)' failed w.show() prog.py:8: GtkWarning: gdk_window_set_focus_on_map: assertion `GDK_IS_WINDOW (window)' failed w.show() prog.py:8: GtkWarning: gdk_window_set_modal_hint: assertion `GDK_IS_WINDOW (window)' failed w.show() prog.py:8: GtkWarning: gtk_window_realize_icon: assertion `widget->window != NULL' failed w.show() prog.py:8: GtkWarning: gdk_window_set_geometry_hints: assertion `GDK_IS_WINDOW (window)' failed w.show() prog.py:8: GtkWarning: gdk_window_unmaximize: assertion `GDK_IS_WINDOW (window)' failed w.show() prog.py:8: GtkWarning: gdk_window_unstick: assertion `GDK_IS_WINDOW (window)' failed w.show() prog.py:8: GtkWarning: gdk_window_deiconify: assertion `GDK_IS_WINDOW (window)' failed w.show() prog.py:8: GtkWarning: gdk_window_unfullscreen: assertion `GDK_IS_WINDOW (window)' failed w.show() prog.py:8: GtkWarning: gdk_window_set_keep_above: assertion `GDK_IS_WINDOW (window)' failed w.show() prog.py:8: GtkWarning: gdk_window_set_keep_below: assertion `GDK_IS_WINDOW (window)' failed w.show() prog.py:8: GtkWarning: gdk_window_show: assertion `GDK_IS_WINDOW (window)' failed w.show() prog.py:11: Warning: g_object_ref: assertion `G_IS_OBJECT (object)' failed w.add(vbox) prog.py:11: GtkWarning: gtk_style_attach: assertion `window != NULL' failed w.add(vbox) prog.py:12: GtkWarning: _gtk_style_peek_property_value: assertion `GTK_IS_STYLE (style)' failed vbox.show() Program received signal SIGSEGV, Segmentation fault.
+ Trace 210629
Thread 139849066989280 (LWP 30806)
Did you check this is specific to PyGTK programs and not just GTK+?
this bug is seen elsewhere. Google found me http://forum.soft32.com/linux2/Bug-425131-python-gtk2-segmentation-fault-DISPLAY-ftopict94540.html I personally see it with ocfs2console, part of ocfs2-tools. It's using pygtk. It was originally reported by a distribution bugzilla. I see it on my Debian laptop as well. Running it from gauche (a scheme) I get a clean exit, but it looks to be a Gtk-WARNING: gosh -I. gtk-hello.scm (<unknown>:18020): Gtk-WARNING **: cannot open display: So it would appear that GTK+ currently reports it as a warning, and pygtk faithfully passes it along as a warning. And every user will segfault, because really, in 2009, we're not supposed to have to handle this ourselves. The proposed solution for ocfs2console was: +import warnings +warnings.simplefilter("error") Personally, I think that is garbage, that a programmer has to filter a standard error just to match the right behavior. But that's what I'm going to have to include if pygtk considers a segfault the right way to behave.
*** Bug 582102 has been marked as a duplicate of this bug. ***
The relevant change was made in response to bug 316877. The bug basically complained that 'import gtk' must not raise just because display cannot be open. That GTK+ is initialized on importing is important. Maybe this can be postponed, but even if so (which I doubt) it is nowhere an easy thing to do. So what would you propose?
First, I would contend that the change for bug 316877 was wrong - hiding an error as a warning isn't a solution; if I have to learn how to turn a warning into an error to actually catch something, it's clearly an error, not a warning. But that's water under the bridge, I guess. Obviously, initializing on import violates the semantics of 'import'. You're doing more than namespace work. That's OK, if you so choose. But you shouldn't segfault! See, this bug is filed because the later calls in the initialization crash when that DISPLAY error isn't triggered. Not "fail without raising, printing a warning", but *CRASH*. That's just unacceptable. Not having a DISPLAY is a valid case, not a weird situation. Inside the mechanism of 'import gtk', the code needs to detect the problem and handle it sanely. Prior to bug 316877, it raised the error from gtk_init(). If you don't want to resume doing so, you could at least notice the error and skip the rest of the pyGtk initialization. It's just going to SEGV anyway.
(In reply to comment #5) > First, I would contend that the change for bug 316877 was wrong - hiding an > error as a warning isn't a solution; if I have to learn how to turn a warning > into an error to actually catch something, it's clearly an error, not a > warning. But that's water under the bridge, I guess. I don't think it can be changed without breaking something. If importing fails with an exception you cannot even check module version. > Obviously, initializing on import violates the semantics of 'import'. Yes, but it is years too late to change. It will break everything. > Inside the mechanism of 'import gtk', the code needs to detect the problem and > handle it sanely. Exactly how? > Prior to bug 316877, it raised the error from gtk_init(). > If you don't want to resume doing so, We can't, see above. > you could at least notice the error and skip the rest of the pyGtk initialization. It's just going to SEGV anyway. It's not initialization that segfaults as I understand. It is code that follows. And it is unfortunately virtually impossible to make sure that nothing in PyGTK ever segfaults, not least because we are a wrapper around GTK+ that doesn't have such a goal. The best thing I can think of that is feasible to implement and is not backward-incompatible is adding e.g. 'gtk.initialized'. You could check its value after importing and before calling any other PyGTK code and branch depending on that. Any other ideas?
I think that gtk.initialized would be a good start. I'd really like to be able to know what the reason for initialization failure was. Is there any way to trap that and put it on gtk.initialized_error or something? But definitely, a way to check success that doesn't involve hijacking the warning system is a good thing.
Actually, you don't need 'gtk.initialized'. Here is code that will detect display stuff: # This will print warning too, but I guess one could live with that. import gtk try: # This will try opening display for the second time if first # one failed, but I think it's not that large of a drawback. gtk.init_check() except RuntimeError: print 'Gahhh, no display' sys.exit() # Work as usually.
The only drawback is hte doubly-printed warning. All pygtk apps should have this code. It certainly is better than the warning hack
pygtk is not under active development anymore and had its last code changes in 2013. Its codebase has been archived: https://gitlab.gnome.org/Archive/pygtk/commits/master PyGObject at https://gitlab.gnome.org/GNOME/pygobject is its successor. See https://pygobject.readthedocs.io/en/latest/guide/porting.html for porting info. Closing this report as WONTFIX as part of Bugzilla Housekeeping to reflect reality. Feel free to open a task in GNOME Gitlab if the issue described in this task still applies to a recent version of PyGObject. Thanks!