gmain: make g_source_add_child_source() thread safe

g_source_add_child_source() releases the context lock before attaching
child_source to context. And this causes trouble if parent source is
blocked and g_main_dispatch() manages to lock the context mutex and call
unblock_source() before child_source gets attached to context.
To fix this we call g_source_attach_unlocked() before releasing the
context mutex.

https://bugzilla.gnome.org/show_bug.cgi?id=711064
This commit is contained in:
Ognyan Tonchev 2013-10-29 16:39:38 +01:00 committed by Dan Winship
parent 89f9615835
commit 64909ff740

View File

@ -1111,7 +1111,8 @@ assign_source_id_unlocked (GMainContext *context,
static guint
g_source_attach_unlocked (GSource *source,
GMainContext *context)
GMainContext *context,
gboolean do_wakeup)
{
GSList *tmp_list;
@ -1136,10 +1137,16 @@ g_source_attach_unlocked (GSource *source,
tmp_list = source->priv->child_sources;
while (tmp_list)
{
g_source_attach_unlocked (tmp_list->data, context);
g_source_attach_unlocked (tmp_list->data, context, FALSE);
tmp_list = tmp_list->next;
}
/* If another thread has acquired the context, wake it up since it
* might be in poll() right now.
*/
if (do_wakeup && context->owner && context->owner != G_THREAD_SELF)
g_wakeup_signal (context->wakeup);
return source->source_id;
}
@ -1168,13 +1175,7 @@ g_source_attach (GSource *source,
LOCK_CONTEXT (context);
result = g_source_attach_unlocked (source, context);
/* If another thread has acquired the context, wake it up since it
* might be in poll() right now.
*/
if (context->owner && context->owner != G_THREAD_SELF)
g_wakeup_signal (context->wakeup);
result = g_source_attach_unlocked (source, context, TRUE);
UNLOCK_CONTEXT (context);
@ -1433,8 +1434,8 @@ g_source_add_child_source (GSource *source,
if (context)
{
g_source_attach_unlocked (child_source, context, TRUE);
UNLOCK_CONTEXT (context);
g_source_attach (child_source, context);
}
}