summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2013-05-30 16:46:02 +0200
committerDan Winship <danw@gnome.org>2013-06-25 09:25:57 -0400
commit1d5c815ecd3a5ac6032e7931491296e693b51ccd (patch)
tree35955977af96139c6d1d8120d5160beb95e11c24
parent5841267a6c046744979fc11ec856265c18c6338c (diff)
downloadglib-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.c34
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)
{