Skip to content

Draft: glib: add a proper weak-ref-like relationship between GSource and GMainContext

Like the GWeakRef's in GObject, there is a global lock that is consulted whenever g_main_context_unref() or g_source_destroy() or g_source_unref() is called to retrieve a reference to the associated GMainContext.

There are a number of actual races that are fixed by this change.

  1. Racing GSource destruction with g_main_context_unref() is solved by holding the global source_weak_locations lock while setting source->context = NULL and while g_source_destroy() attempts to retrieve source->context;
  2. Same race as 1. but inside g_source_unref()
  3. Theoretical race of double freeing the contents of context->pending_dispatches if both g_source_destroy() and g_main_context_unref() both enter g_main_context_unref().

A couple of implementation notes:

  1. Unlocking source_weak_locations too early in g_main_context_unref() (before g_source_destroy_internal() is called) may have a race of the G_HOOK_FLAG_ACTIVE state of the source and cause a leak of the source. This is why source_weak_locations is also held over the calls to g_source_destroy_internal() in g_main_context_unref(). So that either g_main_context_unref() or g_source_destroy()
  2. g_main_context_unref() now needs to be more of a dispose() implementation as it can be called multiple times with losing the last ref.

Fixes: #803

Looking at this I have found another potential g_source_destroy() race with returning FALSE from dispatch() that also needs looking at.

Merge request reports