from gnome bug #669260

gmain: block child sources when blocking the parent

When blocking a source that has child sources, we need to consider the
children blocked as well. Otherwise they will still trigger repeatedly
in an inner loop started from the parent source's callback.

Fixes download dialog not rendered upon certain mimetypes on midori,
see https://bugs.launchpad.net/midori/+bug/780133
This commit is contained in:
landry 2012-04-16 10:04:49 +00:00
parent 6aafab44cc
commit aa6f592e02
2 changed files with 98 additions and 1 deletions

View File

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.168 2012/04/14 07:47:55 ajacoutot Exp $
# $OpenBSD: Makefile,v 1.169 2012/04/16 10:04:49 landry Exp $
COMMENT-main= general-purpose utility library
COMMENT-docs= glib2 documentation
@ -8,6 +8,7 @@ DISTNAME= glib-${VERSION}
EXTRACT_SUFX= .tar.xz
PKGNAME-main= glib2-${VERSION}
REVISION-main= 0
PKGNAME-docs= glib2-docs-${VERSION}
CATEGORIES= devel

View File

@ -0,0 +1,96 @@
$OpenBSD: patch-glib_gmain_c,v 1.12 2012/04/16 10:04:49 landry Exp $
gmain: block child sources when blocking the parent
When blocking a source that has child sources, we need to consider the
children blocked as well. Otherwise they will still trigger repeatedly
in an inner loop started from the parent source's callback.
patch from https://bugzilla.gnome.org/attachment.cgi?id=212002
https://bugzilla.gnome.org/show_bug.cgi?id=669260
Fixes https://bugs.launchpad.net/midori/+bug/780133
--- glib/gmain.c.orig Mon Apr 2 05:08:41 2012
+++ glib/gmain.c Mon Apr 16 10:41:41 2012
@@ -191,7 +191,8 @@ typedef struct _GSourceCallback GSourceCallback;
typedef enum
{
G_SOURCE_READY = 1 << G_HOOK_FLAG_USER_SHIFT,
- G_SOURCE_CAN_RECURSE = 1 << (G_HOOK_FLAG_USER_SHIFT + 1)
+ G_SOURCE_CAN_RECURSE = 1 << (G_HOOK_FLAG_USER_SHIFT + 1),
+ G_SOURCE_BLOCKED = 1 << (G_HOOK_FLAG_USER_SHIFT + 2)
} GSourceFlags;
typedef struct _GMainWaiter GMainWaiter;
@@ -313,8 +314,7 @@ struct _GSourcePrivate
#define G_THREAD_SELF g_thread_self ()
#define SOURCE_DESTROYED(source) (((source)->flags & G_HOOK_FLAG_ACTIVE) == 0)
-#define SOURCE_BLOCKED(source) (((source)->flags & G_HOOK_FLAG_IN_CALL) != 0 && \
- ((source)->flags & G_SOURCE_CAN_RECURSE) == 0)
+#define SOURCE_BLOCKED(source) (((source)->flags & G_SOURCE_BLOCKED) != 0)
#define SOURCE_UNREF(source, context) \
G_STMT_START { \
@@ -2426,12 +2426,24 @@ block_source (GSource *source)
g_return_if_fail (!SOURCE_BLOCKED (source));
+ source->flags |= G_SOURCE_BLOCKED;
+
tmp_list = source->poll_fds;
while (tmp_list)
{
g_main_context_remove_poll_unlocked (source->context, tmp_list->data);
tmp_list = tmp_list->next;
}
+
+ if (source->priv && source->priv->child_sources)
+ {
+ tmp_list = source->priv->child_sources;
+ while (tmp_list)
+ {
+ block_source (tmp_list->data);
+ tmp_list = tmp_list->next;
+ }
+ }
}
/* HOLDS: source->context's lock */
@@ -2440,15 +2452,27 @@ unblock_source (GSource *source)
{
GSList *tmp_list;
- g_return_if_fail (!SOURCE_BLOCKED (source)); /* Source already unblocked */
+ g_return_if_fail (SOURCE_BLOCKED (source)); /* Source already unblocked */
g_return_if_fail (!SOURCE_DESTROYED (source));
+ source->flags &= ~G_SOURCE_BLOCKED;
+
tmp_list = source->poll_fds;
while (tmp_list)
{
g_main_context_add_poll_unlocked (source->context, source->priority, tmp_list->data);
tmp_list = tmp_list->next;
}
+
+ if (source->priv && source->priv->child_sources)
+ {
+ tmp_list = source->priv->child_sources;
+ while (tmp_list)
+ {
+ unblock_source (tmp_list->data);
+ tmp_list = tmp_list->next;
+ }
+ }
}
/* HOLDS: context's lock */
@@ -2527,8 +2551,7 @@ g_main_dispatch (GMainContext *context)
if (!was_in_call)
source->flags &= ~G_HOOK_FLAG_IN_CALL;
- if ((source->flags & G_SOURCE_CAN_RECURSE) == 0 &&
- !SOURCE_DESTROYED (source))
+ if (SOURCE_BLOCKED (source) && !SOURCE_DESTROYED (source))
unblock_source (source);
/* Note: this depends on the fact that we can't switch