From 64909ff7409968b83b0961e053eac98a03bd30cf Mon Sep 17 00:00:00 2001 From: Ognyan Tonchev Date: Tue, 29 Oct 2013 16:39:38 +0100 Subject: [PATCH] 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 --- glib/gmain.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/glib/gmain.c b/glib/gmain.c index 98603f7df..9c37bb28d 100644 --- a/glib/gmain.c +++ b/glib/gmain.c @@ -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); } }