Skip to content

gi/object: Fix g_weak_ref_get deadlocking if used while GC is running

msizanoen1 requested to merge msizanoen1/gjs:fix-deadlock-gjs-gc into master

GObject's weak reference implementation have its own global lock which may result in deadlocking if e.g. another thread calls g_weak_ref_get on a JS-held object while another thread is inside ObjectInstance::disassociate_js_gobject() which eventually leads to the toggle queue being locked by ObjectInstance::wrapped_gobj_toggle_notify() while also holding weak_locations_lock.

Thread 1                                                 | Thread 2
---------------------------------------------------------|--------------------------------------------------------
 ObjectInstance::disassociate_js_gobject()               |
  ToggleQueue::get_default()                             |
   ToggleQueue::lock()                                   |
                                                         | g_weak_ref_get()
                                                         |  g_rw_lock_reader_lock(weak_locations_lock)
                                                         |  g_object_ref()
                                                         |   ObjectInstance::wrapped_gobj_toggle_notify()
                                                         |    ToggleQueue::get_default()
                                                         |     ToggleQueue::lock()
                                                         |      (waits for thread 1 to release toggle queue lock)
   g_object_weak_unref()                                 |
    g_rw_lock_writer_lock(weak_locations_lock)           |
     (waits for thread 2 to release weak_locations_lock) |

Fix this by releasing the toggle queue lock before calling g_object_weak_unref.

Fixes #558 (closed)

Merge request reports