[at-spi2-core/gnome-3-36] Fix handling of event listener removals during an event callback
- From: Mike Gorse <mgorse src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [at-spi2-core/gnome-3-36] Fix handling of event listener removals during an event callback
- Date: Fri, 4 Sep 2020 23:59:20 +0000 (UTC)
commit bc7a17b037cef3dc710b944ec49e461136a703bc
Author: Mike Gorse <mgorse suse com>
Date: Wed Sep 2 17:11:15 2020 -0500
Fix handling of event listener removals during an event callback
We should not modify event_listeners while we are iterating through it.
Otherwise, we may crash. If an event listener is removed from within an event
callback, then defer the removal until the callback has ended.
atspi/atspi-event-listener.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
---
diff --git a/atspi/atspi-event-listener.c b/atspi/atspi-event-listener.c
index d85321cd..38271f8e 100644
--- a/atspi/atspi-event-listener.c
+++ b/atspi/atspi-event-listener.c
@@ -166,6 +166,9 @@ atspi_event_listener_new_simple (AtspiEventListenerSimpleCB callback,
}
static GList *event_listeners = NULL;
+static GList *pending_removals = NULL;
+static int in_send = 0;
+
static gchar *
convert_name_from_dbus (const char *name, gboolean path_hack)
@@ -817,7 +820,10 @@ atspi_event_listener_deregister_from_callback (AtspiEventListenerCB callback,
{
DBusMessage *message, *reply;
l = g_list_next (l);
- event_listeners = g_list_remove (event_listeners, e);
+ if (in_send)
+ pending_removals = g_list_append (pending_removals, e);
+ else
+ event_listeners = g_list_remove (event_listeners, e);
for (i = 0; i < matchrule_array->len; i++)
{
char *matchrule = g_ptr_array_index (matchrule_array, i);
@@ -834,7 +840,8 @@ atspi_event_listener_deregister_from_callback (AtspiEventListenerCB callback,
if (reply)
dbus_message_unref (reply);
- listener_entry_free (e);
+ if (!in_send)
+ listener_entry_free (e);
}
else
l = g_list_next (l);
@@ -909,6 +916,13 @@ detail_matches_listener (const char *event_detail, const char *listener_detail)
: strcmp (listener_detail, event_detail));
}
+static void
+resolve_pending_removal (gpointer data)
+{
+ event_listeners = g_list_remove (event_listeners, data);
+ listener_entry_free (data);
+}
+
void
_atspi_send_event (AtspiEvent *e)
{
@@ -929,6 +943,7 @@ _atspi_send_event (AtspiEvent *e)
g_warning ("AT-SPI: Couldn't parse event: %s\n", e->type);
return;
}
+ in_send++;
for (l = event_listeners; l; l = g_list_next (l))
{
EventListenerEntry *entry = l->data;
@@ -944,16 +959,28 @@ _atspi_send_event (AtspiEvent *e)
break;
}
if (!l2)
+ {
+ for (l2 = pending_removals; l2; l2 = l2->next)
+ {
+ if (l2->data == entry)
+ break;
+ }
+ }
+ if (!l2)
{
entry->callback (atspi_event_copy (e), entry->user_data);
called_listeners = g_list_prepend (called_listeners, entry);
}
}
}
+ in_send--;
if (detail) g_free (detail);
g_free (name);
g_free (category);
g_list_free (called_listeners);
+
+ g_list_free_full (pending_removals, resolve_pending_removal);
+ pending_removals = NULL;
}
DBusHandlerResult
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]