diff options
author | Wim Taymans <wim.taymans@collabora.co.uk> | 2013-05-30 16:46:02 +0200 |
---|---|---|
committer | Dan Winship <danw@gnome.org> | 2013-06-25 09:25:57 -0400 |
commit | 1d5c815ecd3a5ac6032e7931491296e693b51ccd (patch) | |
tree | 35955977af96139c6d1d8120d5160beb95e11c24 | |
parent | 5841267a6c046744979fc11ec856265c18c6338c (diff) | |
download | glib-1d5c815ecd3a5ac6032e7931491296e693b51ccd.tar.gz |
gmain: handle blocked source in g_source_add_child_source()
When a child_source is added to a blocked source it has no context, yet we
call block_source on it that segfaults when it dereferences the NULL context
when it attempts to remove the file descriptors. To fix this we:
- Ensure that when we block a source, we don't attempt to remove its file
descriptors from a NULL context.
- Also ensure that when we attach a blocked source to a context, we don't add the
file descriptors to the context.
https://bugzilla.gnome.org/show_bug.cgi?id=701283
-rw-r--r-- | glib/gmain.c | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/glib/gmain.c b/glib/gmain.c index cf219fe3c..3c6610855 100644 --- a/glib/gmain.c +++ b/glib/gmain.c @@ -1118,15 +1118,18 @@ g_source_attach_unlocked (GSource *source, source->ref_count++; source_add_to_context (source, context); - tmp_list = source->poll_fds; - while (tmp_list) + if (!SOURCE_BLOCKED (source)) { - g_main_context_add_poll_unlocked (context, source->priority, tmp_list->data); - tmp_list = tmp_list->next; - } + tmp_list = source->poll_fds; + while (tmp_list) + { + g_main_context_add_poll_unlocked (context, source->priority, tmp_list->data); + tmp_list = tmp_list->next; + } - for (tmp_list = source->priv->fds; tmp_list; tmp_list = tmp_list->next) - g_main_context_add_poll_unlocked (context, source->priority, tmp_list->data); + for (tmp_list = source->priv->fds; tmp_list; tmp_list = tmp_list->next) + g_main_context_add_poll_unlocked (context, source->priority, tmp_list->data); + } tmp_list = source->priv->child_sources; while (tmp_list) @@ -2941,15 +2944,18 @@ block_source (GSource *source) source->flags |= G_SOURCE_BLOCKED; - tmp_list = source->poll_fds; - while (tmp_list) + if (source->context) { - g_main_context_remove_poll_unlocked (source->context, tmp_list->data); - tmp_list = tmp_list->next; - } + tmp_list = source->poll_fds; + while (tmp_list) + { + g_main_context_remove_poll_unlocked (source->context, tmp_list->data); + tmp_list = tmp_list->next; + } - for (tmp_list = source->priv->fds; tmp_list; tmp_list = tmp_list->next) - g_main_context_remove_poll_unlocked (source->context, tmp_list->data); + for (tmp_list = source->priv->fds; tmp_list; tmp_list = tmp_list->next) + g_main_context_remove_poll_unlocked (source->context, tmp_list->data); + } if (source->priv && source->priv->child_sources) { |