[glib/gdbus] Process D-Bus messages in idle to avoid reentrancy issues
- From: David Zeuthen <davidz src gnome org>
- To: svn-commits-list gnome org
- Subject: [glib/gdbus] Process D-Bus messages in idle to avoid reentrancy issues
- Date: Tue, 28 Apr 2009 11:02:04 -0400 (EDT)
commit ccb19719e7206b5578aa9d34af9775aaa938be42
Author: David Zeuthen <davidz redhat com>
Date: Tue Apr 28 10:53:16 2009 -0400
Process D-Bus messages in idle to avoid reentrancy issues
We might want to remove this after auditing what really is going on /
fixing the bugs it causes. Suffice to say, this is needed right now to
handle recursive mainloops being started from D-Bus signal handlers
(e.g. on_bus_name_appeared). While recursive mainloops is generally
frowned upon, we rely on this in our test cases.
---
gdbus/gbusnameowner.c | 54 +++++++++++++++++++++++++++++++++++++++----
gdbus/gbusnamewatcher.c | 58 ++++++++++++++++++++++++++++++++++++++++++----
gdbus/gdbusconnection.c | 55 +++++++++++++++++++++++++++++++++++++++-----
3 files changed, 151 insertions(+), 16 deletions(-)
diff --git a/gdbus/gbusnameowner.c b/gdbus/gbusnameowner.c
index 9db45c1..d76df78 100644
--- a/gdbus/gbusnameowner.c
+++ b/gdbus/gbusnameowner.c
@@ -58,6 +58,10 @@ struct _GBusNameOwnerPrivate
gboolean owns_name;
gboolean is_initialized;
+
+ /* stack of messages to process in idle */
+ GPtrArray *idle_processing_messages;
+ guint idle_processing_event_source_id;
};
enum
@@ -162,6 +166,14 @@ g_bus_name_owner_finalize (GObject *object)
}
g_free (owner->priv->name);
+ if (owner->priv->idle_processing_event_source_id > 0)
+ g_source_remove (owner->priv->idle_processing_event_source_id);
+ if (owner->priv->idle_processing_messages != NULL)
+ {
+ g_ptr_array_foreach (owner->priv->idle_processing_messages, (GFunc) dbus_message_unref, NULL);
+ g_ptr_array_free (owner->priv->idle_processing_messages, TRUE);
+ }
+
if (G_OBJECT_CLASS (g_bus_name_owner_parent_class)->finalize != NULL)
G_OBJECT_CLASS (g_bus_name_owner_parent_class)->finalize (object);
}
@@ -277,12 +289,10 @@ g_bus_name_owner_set_property (GObject *object,
dbus_message_get_member (message)); \
} while (FALSE)
-static DBusHandlerResult
-filter_function (DBusConnection *dbus_1_connection,
- DBusMessage *message,
- void *user_data)
+static void
+process_message (GBusNameOwner *owner,
+ DBusMessage *message)
{
- GBusNameOwner *owner = G_BUS_NAME_OWNER (user_data);
DBusError dbus_error;
const gchar *name;
gboolean old_owns_name;
@@ -357,6 +367,40 @@ filter_function (DBusConnection *dbus_1_connection,
dbus_error_free (&dbus_error);
}
}
+}
+
+static gboolean
+process_messages_in_idle (gpointer user_data)
+{
+ GBusNameOwner *owner = G_BUS_NAME_OWNER (user_data);
+ guint n;
+
+ for (n = 0; n < owner->priv->idle_processing_messages->len; n++)
+ {
+ DBusMessage *message = owner->priv->idle_processing_messages->pdata[n];
+ process_message (owner, message);
+ dbus_message_unref (message);
+ }
+
+ g_ptr_array_remove_range (owner->priv->idle_processing_messages,
+ 0,
+ owner->priv->idle_processing_messages->len);
+ owner->priv->idle_processing_event_source_id = 0;
+ return FALSE;
+}
+
+static DBusHandlerResult
+filter_function (DBusConnection *dbus_1_connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GBusNameOwner *owner = G_BUS_NAME_OWNER (user_data);
+
+ if (owner->priv->idle_processing_messages == NULL)
+ owner->priv->idle_processing_messages = g_ptr_array_new ();
+ g_ptr_array_add (owner->priv->idle_processing_messages, dbus_message_ref (message));
+ if (owner->priv->idle_processing_event_source_id == 0)
+ owner->priv->idle_processing_event_source_id = g_idle_add (process_messages_in_idle, owner);
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
diff --git a/gdbus/gbusnamewatcher.c b/gdbus/gbusnamewatcher.c
index e0a4321..2e8da33 100644
--- a/gdbus/gbusnamewatcher.c
+++ b/gdbus/gbusnamewatcher.c
@@ -59,6 +59,10 @@ struct _GBusNameWatcherPrivate
gchar *match_rule;
gboolean is_initialized;
+
+ /* stack of messages to process in idle */
+ GPtrArray *idle_processing_messages;
+ guint idle_processing_event_source_id;
};
enum
@@ -160,6 +164,14 @@ g_bus_name_watcher_finalize (GObject *object)
g_free (watcher->priv->name);
g_free (watcher->priv->name_owner);
+ if (watcher->priv->idle_processing_event_source_id > 0)
+ g_source_remove (watcher->priv->idle_processing_event_source_id);
+ if (watcher->priv->idle_processing_messages != NULL)
+ {
+ g_ptr_array_foreach (watcher->priv->idle_processing_messages, (GFunc) dbus_message_unref, NULL);
+ g_ptr_array_free (watcher->priv->idle_processing_messages, TRUE);
+ }
+
if (G_OBJECT_CLASS (g_bus_name_watcher_parent_class)->finalize != NULL)
G_OBJECT_CLASS (g_bus_name_watcher_parent_class)->finalize (object);
}
@@ -267,12 +279,12 @@ g_bus_name_watcher_set_property (GObject *object,
dbus_message_get_member (message)); \
} while (FALSE)
-static DBusHandlerResult
-filter_function (DBusConnection *dbus_1_connection,
- DBusMessage *message,
- void *user_data)
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+process_message (GBusNameWatcher *watcher,
+ DBusMessage *message)
{
- GBusNameWatcher *watcher = G_BUS_NAME_WATCHER (user_data);
const gchar *name;
const gchar *old_owner;
const gchar *new_owner;
@@ -325,6 +337,42 @@ filter_function (DBusConnection *dbus_1_connection,
}
out:
+ ;
+}
+
+static gboolean
+process_messages_in_idle (gpointer user_data)
+{
+ GBusNameWatcher *watcher = G_BUS_NAME_WATCHER (user_data);
+ guint n;
+
+ for (n = 0; n < watcher->priv->idle_processing_messages->len; n++)
+ {
+ DBusMessage *message = watcher->priv->idle_processing_messages->pdata[n];
+ process_message (watcher, message);
+ dbus_message_unref (message);
+ }
+
+ g_ptr_array_remove_range (watcher->priv->idle_processing_messages,
+ 0,
+ watcher->priv->idle_processing_messages->len);
+ watcher->priv->idle_processing_event_source_id = 0;
+ return FALSE;
+}
+
+static DBusHandlerResult
+filter_function (DBusConnection *dbus_1_connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GBusNameWatcher *watcher = G_BUS_NAME_WATCHER (user_data);
+
+ if (watcher->priv->idle_processing_messages == NULL)
+ watcher->priv->idle_processing_messages = g_ptr_array_new ();
+ g_ptr_array_add (watcher->priv->idle_processing_messages, dbus_message_ref (message));
+ if (watcher->priv->idle_processing_event_source_id == 0)
+ watcher->priv->idle_processing_event_source_id = g_idle_add (process_messages_in_idle, watcher);
+
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
diff --git a/gdbus/gdbusconnection.c b/gdbus/gdbusconnection.c
index a2ad3c9..4850b26 100644
--- a/gdbus/gdbusconnection.c
+++ b/gdbus/gdbusconnection.c
@@ -68,6 +68,10 @@ struct _GDBusConnectionPrivate
guint global_pending_call_id;
GHashTable *pending_call_id_to_simple;
+
+ /* stack of messages to process in idle */
+ GPtrArray *idle_processing_messages;
+ guint idle_processing_event_source_id;
};
enum
@@ -143,6 +147,14 @@ g_dbus_connection_finalize (GObject *object)
g_hash_table_destroy (connection->priv->pending_call_id_to_simple);
+ if (connection->priv->idle_processing_event_source_id > 0)
+ g_source_remove (connection->priv->idle_processing_event_source_id);
+ if (connection->priv->idle_processing_messages != NULL)
+ {
+ g_ptr_array_foreach (connection->priv->idle_processing_messages, (GFunc) dbus_message_unref, NULL);
+ g_ptr_array_free (connection->priv->idle_processing_messages, TRUE);
+ }
+
if (G_OBJECT_CLASS (g_dbus_connection_parent_class)->finalize != NULL)
G_OBJECT_CLASS (g_dbus_connection_parent_class)->finalize (object);
}
@@ -657,19 +669,16 @@ setup_reconnect_timer (GDBusConnection *connection)
dbus_message_get_member (message)); \
} while (FALSE)
-static DBusHandlerResult
-filter_function (DBusConnection *dbus_1_connection,
- DBusMessage *message,
- void *user_data)
+static void
+process_message (GDBusConnection *connection,
+ DBusMessage *message)
{
- GDBusConnection *connection = G_DBUS_CONNECTION (user_data);
DBusError dbus_error;
//g_debug ("in filter_function for dbus_1_connection %p", dbus_1_connection);
//PRINT_MESSAGE (message);
dbus_error_init (&dbus_error);
-
/* check if we are disconnected from the bus */
if (dbus_message_is_signal (message,
DBUS_INTERFACE_LOCAL,
@@ -690,6 +699,40 @@ filter_function (DBusConnection *dbus_1_connection,
setup_reconnect_timer (connection);
}
}
+}
+
+static gboolean
+process_messages_in_idle (gpointer user_data)
+{
+ GDBusConnection *connection = G_DBUS_CONNECTION (user_data);
+ guint n;
+
+ for (n = 0; n < connection->priv->idle_processing_messages->len; n++)
+ {
+ DBusMessage *message = connection->priv->idle_processing_messages->pdata[n];
+ process_message (connection, message);
+ dbus_message_unref (message);
+ }
+
+ g_ptr_array_remove_range (connection->priv->idle_processing_messages,
+ 0,
+ connection->priv->idle_processing_messages->len);
+ connection->priv->idle_processing_event_source_id = 0;
+ return FALSE;
+}
+
+static DBusHandlerResult
+filter_function (DBusConnection *dbus_1_connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GDBusConnection *connection = G_DBUS_CONNECTION (user_data);
+
+ if (connection->priv->idle_processing_messages == NULL)
+ connection->priv->idle_processing_messages = g_ptr_array_new ();
+ g_ptr_array_add (connection->priv->idle_processing_messages, dbus_message_ref (message));
+ if (connection->priv->idle_processing_event_source_id == 0)
+ connection->priv->idle_processing_event_source_id = g_idle_add (process_messages_in_idle, connection);
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]