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
This commit is contained in:
Wim Taymans 2013-05-30 16:46:02 +02:00 committed by Dan Winship
parent 5841267a6c
commit 1d5c815ecd

View File

@ -1118,6 +1118,8 @@ g_source_attach_unlocked (GSource *source,
source->ref_count++; source->ref_count++;
source_add_to_context (source, context); source_add_to_context (source, context);
if (!SOURCE_BLOCKED (source))
{
tmp_list = source->poll_fds; tmp_list = source->poll_fds;
while (tmp_list) while (tmp_list)
{ {
@ -1127,6 +1129,7 @@ g_source_attach_unlocked (GSource *source,
for (tmp_list = source->priv->fds; tmp_list; 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); g_main_context_add_poll_unlocked (context, source->priority, tmp_list->data);
}
tmp_list = source->priv->child_sources; tmp_list = source->priv->child_sources;
while (tmp_list) while (tmp_list)
@ -2941,6 +2944,8 @@ block_source (GSource *source)
source->flags |= G_SOURCE_BLOCKED; source->flags |= G_SOURCE_BLOCKED;
if (source->context)
{
tmp_list = source->poll_fds; tmp_list = source->poll_fds;
while (tmp_list) while (tmp_list)
{ {
@ -2950,6 +2955,7 @@ block_source (GSource *source)
for (tmp_list = source->priv->fds; tmp_list; 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); g_main_context_remove_poll_unlocked (source->context, tmp_list->data);
}
if (source->priv && source->priv->child_sources) if (source->priv && source->priv->child_sources)
{ {