gmain: Unref GSourceCallbackFuncs _before_ finalising GSource

Rather than unreffing them _after_ finalising the GSource and freeing
its struct. This fixes the case where the GSourceCallbackFuncs data
contains a pointer to the GSource, and the unref() function operates on
that pointer, e.g. by calling g_source_destroy(). This happens when
using g_source_set_dummy_callback() on a GSource, as the generated
GClosure needs to destroy the GSource when it is invalidated, which
could happen (at latest) when the GSourceCallbackFuncs.unref() function
is called during finalisation of the GSource.

By moving the GSourceCallbackFuncs.unref() invocation higher up in
g_source_unref_internal(), it becomes re-entrancy-safe for GSource
methods.

https://bugzilla.gnome.org/show_bug.cgi?id=692034
This commit is contained in:
Philip Withnall 2014-09-25 10:18:39 +01:00 committed by Philip Withnall
parent ed620183cb
commit 90dd9ff363

View File

@ -2122,6 +2122,21 @@ g_source_unref_internal (GSource *source,
source->ref_count--;
}
if (old_cb_funcs)
{
/* Temporarily increase the ref count again so that GSource methods
* can be called from callback_funcs.unref(). */
source->ref_count++;
if (context)
UNLOCK_CONTEXT (context);
old_cb_funcs->unref (old_cb_data);
if (context)
LOCK_CONTEXT (context);
source->ref_count--;
}
g_free (source->name);
source->name = NULL;
@ -2146,20 +2161,9 @@ g_source_unref_internal (GSource *source,
g_free (source);
}
if (!have_lock && context)
UNLOCK_CONTEXT (context);
if (old_cb_funcs)
{
if (have_lock)
UNLOCK_CONTEXT (context);
old_cb_funcs->unref (old_cb_data);
if (have_lock)
LOCK_CONTEXT (context);
}
}
/**