mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-26 15:36:14 +01:00
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. https://bugzilla.gnome.org/show_bug.cgi?id=669260
This commit is contained in:
parent
b3b32be1e1
commit
a49568cecc
35
glib/gmain.c
35
glib/gmain.c
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user