Bug#758619: more complete backtrace

Simon McVittie smcv at debian.org
Wed Aug 20 20:46:54 UTC 2014


Did you upgrade a package recently that could have triggered this, i.e.
related to Python, GLib, Gtk 2 or reportbug? I would be interested to
know why this is new.

Some analysis below. I think this is probably a pygtk bug, but there is
a workaround that reportbug could use.

On 20/08/14 12:15, VALETTE Eric OLNC/OLPS wrote:
> #2  0x00007ffff2cdc85d in g_mutex_unlock_slowpath (mutex=<optimized
> out>, prev=<optimized out>)                
>     at
> /build/glib2.0-MHsCdQ/glib2.0-2.41.2/./glib/gthread-posix.c:1327                                        
> 
> #3  0x00007ffff19f4bbf in IA__gtk_main () at
> /build/gtk+2.0-zztKf7/gtk+2.0-2.24.24/gtk/gtkmain.c:1256          
> #4  0x00007ffff20a7d54 in _loop
> ()                                                                             
> 
>     at
> /build/buildd-pygtk_2.24.0-3+b1-amd64-HH_0XF/pygtk-2.24.0/gtk/gtk.override:126                          
> 
> #5  0x00007ffff4148b21 in readline_until_enter_or_signal
> (signal=<synthetic pointer>, prompt=<optimized out>)  
>     at
> /build/python2.7-WkYSEh/python2.7-2.7.8/Modules/readline.c:996

"_loop()" is pygtk's implementation of PyOS_ImportHook, which takes the
Python GIL and calls gtk_main():

    gstate = PyGILState_Ensure();
    gtk_main();
    PyGILState_Release(gstate);

gtk_main() releases the GDK mutex before calling g_main_loop_run(), and
reacquires it afterwards:

  if (g_main_loop_is_running (main_loops->data))
    {
      GDK_THREADS_LEAVE ();
      g_main_loop_run (loop);
      GDK_THREADS_ENTER ();
      gdk_flush ();
    }

which means it is not safe to call gtk_main() without holding the GDK
mutex (it is documented that only the thread holding the GDK mutex can
safely call Gtk functions, so that seems reasonable).

However, pygtk doing this in an input hook seems wrong, because I don't
see anything that would guarantee that all invocations of Python's
readline wrapper will be done from a thread that currently holds the GDK
mutex. There is also nothing to say that invocations of the readline
wrapper *won't* be done from a thread that holds the GDK mutex; so there
doesn't seem to be any way this can be done safely?

I don't know what code in reportbug is triggering this hook. One
possible solution would be for reportbug to call gtk.set_interactive(0)
to avoid registering this hook, since the hook's intended use seems to
be for the interactive Python prompt rather than "real applications", so
reportbug probably gets nothing useful from it.

pygtk is deprecated upstream, and python-gi does not have this hook, so
I think it's rather unlikely that this hook will be fixed in pygtk,
except possibly via deletion.

I don't think GLib is really doing anything wrong by crashing here: the
C code in pygtk is asking to unlock a mutex that is not actually locked,
which is a symptom of doing locking in a way that can't possibly be
reliable, so I would be inclined to put it in the category of "undefined
behaviour".

The only way I can think of to make this hook reliable would be for
pygtk to use gdk_threads_set_lock_functions() before gdk_threads_init(),
to replace gdk_threads_enter and gdk_threads_leave with functions that
use a recursive mutex:

    GRecMutex rmutex;

    init()
    {
      gdk_threads_set_lock_functions (enter, leave);
      gdk_threads_init ();
    }

    enter()
    {
      g_rec_mutex_lock (&rmutex);
    }

    leave()
    {
      g_rec_mutex_unlock (&rmutex);
    }

and then make _loop() ensure that the rmutex is locked while it calls
gtk_main(). However, it would be necessary to be rather careful about
lock acquisition order between rmutex and the GIL, to avoid deadlocking
between one thread that is holding rmutex and wants the GIL, and another
thread that is holding the GIL and wants rmutex; so this plan is
probably flawed too.

Regards,
    S



More information about the pkg-gnome-maintainers mailing list