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 563823 - segfault with invalid $DISPLAY
segfault with invalid $DISPLAY
Status: RESOLVED WONTFIX
Product: pygtk
Classification: Bindings
Component: gtk
Git Master
Other Linux
: Normal normal
: ---
Assigned To: Nobody's working on this now (help wanted and appreciated)
Python bindings maintainers
gnome[unmaintained]
: 582102 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2008-12-09 09:06 UTC by Josselin Mouette
Modified: 2018-08-17 13:34 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Josselin Mouette 2008-12-09 09:06:27 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.

Thread 139849066989280 (LWP 30806)

  • #0 IA__gtk_widget_style_get_valist
    at /scratch/build-area/gtk+2.0-2.14.4/gtk/gtkwidget.c line 9051
  • #1 IA__gtk_widget_style_get
    at /scratch/build-area/gtk+2.0-2.14.4/gtk/gtkwidget.c line 9085
  • #2 gtk_widget_get_draw_rectangle
    at /scratch/build-area/gtk+2.0-2.14.4/gtk/gtkwidget.c line 3496
  • #3 gtk_widget_queue_shallow_draw
    at /scratch/build-area/gtk+2.0-2.14.4/gtk/gtkwidget.c line 3780
  • #4 IA__gtk_widget_queue_resize
    at /scratch/build-area/gtk+2.0-2.14.4/gtk/gtkwidget.c line 3609
  • #5 IA__gtk_widget_show
    at /scratch/build-area/gtk+2.0-2.14.4/gtk/gtkwidget.c line 3002
  • #6 ??
    from /var/lib/python-support/python2.5/gtk-2.0/gtk/_gtk.so
  • #7 PyEval_EvalFrameEx
    at ../Python/ceval.c line 3559
  • #8 PyEval_EvalCodeEx
    at ../Python/ceval.c line 2838
  • #9 PyEval_EvalCode
    at ../Python/ceval.c line 494
  • #10 PyRun_FileExFlags
    at ../Python/pythonrun.c line 1273
  • #11 PyRun_SimpleFileExFlags
    at ../Python/pythonrun.c line 879
  • #12 Py_Main
    at ../Modules/main.c line 532
  • #13 __libc_start_main
    from /lib/libc.so.6
  • #14 _start

Comment 1 Paul Pogonyshev 2008-12-09 19:50:46 UTC
Did you check this is specific to PyGTK programs and not just GTK+?
Comment 2 Joel Becker 2009-02-02 10:55:11 UTC
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.

Comment 3 Paul Pogonyshev 2009-05-10 22:25:29 UTC
*** Bug 582102 has been marked as a duplicate of this bug. ***
Comment 4 Paul Pogonyshev 2009-06-17 22:26:23 UTC
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?
Comment 5 Joel Becker 2009-06-17 22:43:31 UTC
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.
Comment 6 Paul Pogonyshev 2009-06-18 19:14:15 UTC
(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?
Comment 7 Joel Becker 2009-06-18 19:28:08 UTC
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.
Comment 8 Paul Pogonyshev 2009-06-18 21:31:47 UTC
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.
Comment 9 Joel Becker 2009-06-18 21:39:46 UTC
The only drawback is hte doubly-printed warning.  All pygtk apps should have this code.  It certainly is better than the warning hack
Comment 10 André Klapper 2018-08-17 13:34:39 UTC
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!