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 320886 - GSource is unreffed while holding main context lock
GSource is unreffed while holding main context lock
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: mainloop
2.8.x
Other Linux
: Normal major
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2005-11-07 15:42 UTC by Andy Wingo
Modified: 2011-02-18 16:13 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Andy Wingo 2005-11-07 15:42:22 UTC
Version details: latest breezy

I am seeing a lockup in a program. Here are partial stack traces from two threads:

  • #0 sem_wait
    from /lib/libpthread.so.0
  • #1 PyThread_acquire_lock
  • #2 PyEval_RestoreThread
  • #3 PyGILState_Ensure
  • #4 ??
    from /usr/lib/python2.4/site-packages/gtk-2.0/gobject.so
  • #5 g_source_callback_unref
    at gmain.c line 1189
  • #6 IA__g_main_context_dispatch
    at gmain.c line 1942
  • #7 g_main_context_iterate
    at gmain.c line 2565
  • #8 IA__g_main_loop_run
    at gmain.c line 2769
  • #9 initgobject
    from /usr/lib/python2.4/site-packages/gtk-2.0/gobject.so
  • #10 PyEval_EvalFrame
  • #11 PyEval_EvalCodeEx
  • #12 PyEval_EvalFrame
  • #0 __lll_mutex_lock_wait
    from /lib/libpthread.so.0
  • #1 g__main_loop_lock
    from /usr/lib/libglib-2.0.so.0
  • #2 ??
  • #3 pthread_mutex_lock
    from /lib/libpthread.so.0
  • #4 ??
  • #5 Py_BuildValue
  • #6 ??
    from /usr/lib/python2.4/site-packages/gtk-2.0/gobject.so
  • #7 PyEval_EvalFrame
  • #8 PyEval_EvalCodeEx
  • #9 PyFunction_SetClosure
  • #10 PyObject_Call
  • #11 PyEval_CallObjectWithKeywords
  • #12 initgobject
    from /usr/lib/python2.4/site-packages/gtk-2.0/gobject.so
  • #13 IA__g_closure_invoke
    at gclosure.c line 492
  • #14 signal_emit_unlocked_R
    at gsignal.c line 2485
  • #15 IA__g_signal_emit_valist
    at gsignal.c line 2244
  • #16 IA__g_signal_emit
    at gsignal.c line 2288
  • #17 gst_object_dispatch_properties_changed
    at gstobject.c line 610
  • #18 IA__g_object_notify
    at gobjectnotifyqueue.c line 123
  • #19 gst_pad_set_caps
    at gstpad.c line 2158


When in python, code holds the python global interpreter lock (GIL lock). The
main python thread drops the GIL lock and goes into g_main_loop_run().

Then a property notification comes in from another thread. This grabs the GIL
lock, does a g_idle_add to push a python GSource onto the main context (grabbing
the context lock), and then drops out.

The main thread gets around to handling the python GSource, which calls the
gsource without the main context lock. It grabs the GIL lock, does its thing,
and then releases it. Then because the idle handler returned FALSE,
g_main_dispatch unrefs the closure. However it calls the unref function with the
main context lock, and the unref function will grab the GIL lock.

In the mean time if the other thread does a g_idle_add from within the GIL lock
we have a nice ABBA deadlock.

Am working on a patch.
Comment 1 Andy Wingo 2005-11-07 15:52:09 UTC
I think it's sufficient just to move the LOCK_CONTEXT line from gmain.c:1939 to
after then unref at line 1942. All of the other calls to
GSourceCallbackFuncs->unref in an explicitly-unlocked section, e.g. lines 969,
1168, and 1439.
Comment 2 Matthias Clasen 2005-11-07 16:54:26 UTC
I think you are right about the unref. I wonder about the calls to
cb_funcs->ref and cb_funcs->get in g_main_dispatch() though, which 
are both done with the context lock held.
Comment 3 Wim Taymans 2005-11-07 17:57:02 UTC
both ->get and ->ref don't go outside of their functions, ->unref does though.
AFAICS
Comment 4 Matthias Clasen 2005-11-07 17:59:24 UTC
ah, ok

looks good then
Comment 5 Matthias Clasen 2005-11-07 20:16:50 UTC
2005-11-07  Matthias Clasen  <mclasen@redhat.com>

	* glib/gmain.c (g_main_dispatch): Don't call cb_funcs->unref
	while holding the context lock.  (#320886, Andy Wingo)