From 4e7ef619ebe025bd97d2a3ef8dd8c1b7baa903b2 Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Mon, 29 Aug 2011 16:20:50 -0400 Subject: [PATCH] GDBusObjectManagerClient: Add locking Signed-off-by: David Zeuthen --- gio/gdbusobjectmanagerclient.c | 107 +++++++++++++++++++++++++++++++++-------- 1 file changed, 88 insertions(+), 19 deletions(-) diff --git a/gio/gdbusobjectmanagerclient.c b/gio/gdbusobjectmanagerclient.c index 9e8368d..2f581db 100644 --- a/gio/gdbusobjectmanagerclient.c +++ b/gio/gdbusobjectmanagerclient.c @@ -125,6 +125,8 @@ struct _GDBusObjectManagerClientPrivate { + GMutex *lock; + GBusType bus_type; GDBusConnection *connection; gchar *object_path; @@ -212,15 +214,17 @@ g_dbus_object_manager_client_finalize (GObject *object) if (manager->priv->get_proxy_type_destroy_notify != NULL) manager->priv->get_proxy_type_destroy_notify (manager->priv->get_proxy_type_user_data); + g_mutex_free (manager->priv->lock); + if (G_OBJECT_CLASS (g_dbus_object_manager_client_parent_class)->finalize != NULL) G_OBJECT_CLASS (g_dbus_object_manager_client_parent_class)->finalize (object); } static void g_dbus_object_manager_client_get_property (GObject *_object, - guint prop_id, - GValue *value, - GParamSpec *pspec) + guint prop_id, + GValue *value, + GParamSpec *pspec) { GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_object); @@ -254,9 +258,9 @@ g_dbus_object_manager_client_get_property (GObject *_object, static void g_dbus_object_manager_client_set_property (GObject *_object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) + guint prop_id, + const GValue *value, + GParamSpec *pspec) { GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_object); @@ -568,6 +572,7 @@ g_dbus_object_manager_client_init (GDBusObjectManagerClient *manager) manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, G_TYPE_DBUS_OBJECT_MANAGER_CLIENT, GDBusObjectManagerClientPrivate); + manager->priv->lock = g_mutex_new (); manager->priv->map_object_path_to_object_proxy = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, @@ -707,7 +712,7 @@ g_dbus_object_manager_client_new (GDBusConnection *connection, */ GDBusObjectManager * g_dbus_object_manager_client_new_finish (GAsyncResult *res, - GError **error) + GError **error) { GObject *object; GObject *source_object; @@ -894,8 +899,12 @@ g_dbus_object_manager_client_new_for_bus_finish (GAsyncResult *res, GDBusConnection * g_dbus_object_manager_client_get_connection (GDBusObjectManagerClient *manager) { + GDBusConnection *ret; g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL); - return manager->priv->connection; + g_mutex_lock (manager->priv->lock); + ret = manager->priv->connection; + g_mutex_unlock (manager->priv->lock); + return ret; } /** @@ -912,8 +921,12 @@ g_dbus_object_manager_client_get_connection (GDBusObjectManagerClient *manager) const gchar * g_dbus_object_manager_client_get_name (GDBusObjectManagerClient *manager) { + const gchar *ret; g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL); - return manager->priv->name; + g_mutex_lock (manager->priv->lock); + ret = manager->priv->name; + g_mutex_unlock (manager->priv->lock); + return ret; } /** @@ -930,8 +943,12 @@ g_dbus_object_manager_client_get_name (GDBusObjectManagerClient *manager) GDBusObjectManagerClientFlags g_dbus_object_manager_client_get_flags (GDBusObjectManagerClient *manager) { + GDBusObjectManagerClientFlags ret; g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE); - return manager->priv->flags; + g_mutex_lock (manager->priv->lock); + ret = manager->priv->flags; + g_mutex_unlock (manager->priv->lock); + return ret; } /** @@ -951,8 +968,12 @@ g_dbus_object_manager_client_get_flags (GDBusObjectManagerClient *manager) gchar * g_dbus_object_manager_client_get_name_owner (GDBusObjectManagerClient *manager) { + gchar *ret; g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL); - return g_strdup (manager->priv->name_owner); + g_mutex_lock (manager->priv->lock); + ret = g_strdup (manager->priv->name_owner); + g_mutex_unlock (manager->priv->lock); + return ret; } /* ---------------------------------------------------------------------------------------------------- */ @@ -973,9 +994,15 @@ signal_cb (GDBusConnection *connection, GDBusObjectProxy *object_proxy; GDBusInterface *interface; + g_mutex_lock (manager->priv->lock); object_proxy = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path); if (object_proxy == NULL) - goto out; + { + g_mutex_unlock (manager->priv->lock); + goto out; + } + g_object_ref (object_proxy); + g_mutex_unlock (manager->priv->lock); //g_debug ("yay, signal_cb %s %s: %s\n", signal_name, object_path, g_variant_print (parameters, TRUE)); @@ -1062,7 +1089,8 @@ signal_cb (GDBusConnection *connection, } out: - ; + if (object_proxy != NULL) + g_object_ref (object_proxy); } static void @@ -1196,6 +1224,7 @@ on_notify_g_name_owner (GObject *object, gchar *old_name_owner; gchar *new_name_owner; + g_mutex_lock (manager->priv->lock); old_name_owner = manager->priv->name_owner; new_name_owner = g_dbus_proxy_get_name_owner (manager->priv->control_proxy); manager->priv->name_owner = NULL; @@ -1205,16 +1234,19 @@ on_notify_g_name_owner (GObject *object, GList *l; GList *proxies; + /* remote manager changed; nuke all local proxies */ + proxies = g_hash_table_get_values (manager->priv->map_object_path_to_object_proxy); + g_list_foreach (proxies, (GFunc) g_object_ref, NULL); + g_hash_table_remove_all (manager->priv->map_object_path_to_object_proxy); + + g_mutex_unlock (manager->priv->lock); + /* do the :name-owner notify with a NULL name - this way the user knows * the ::object-proxy-removed following is because the name owner went * away */ g_object_notify (G_OBJECT (manager), "name-owner"); - /* remote manager changed; nuke all local proxies */ - proxies = g_hash_table_get_values (manager->priv->map_object_path_to_object_proxy); - g_list_foreach (proxies, (GFunc) g_object_ref, NULL); - g_hash_table_remove_all (manager->priv->map_object_path_to_object_proxy); for (l = proxies; l != NULL; l = l->next) { GDBusObjectProxy *object_proxy = G_DBUS_OBJECT_PROXY (l->data); @@ -1226,6 +1258,10 @@ on_notify_g_name_owner (GObject *object, /* nuke local filter */ maybe_unsubscribe_signals (manager); } + else + { + g_mutex_unlock (manager->priv->lock); + } if (new_name_owner != NULL) { @@ -1263,7 +1299,9 @@ on_notify_g_name_owner (GObject *object, /* do the :name-owner notify *AFTER* emitting ::object-proxy-added signals - this * way the user knows that the signals were emitted because the name owner came back */ + g_mutex_lock (manager->priv->lock); manager->priv->name_owner = new_name_owner; + g_mutex_unlock (manager->priv->lock); g_object_notify (G_OBJECT (manager), "name-owner"); } @@ -1379,10 +1417,16 @@ add_interfaces (GDBusObjectManagerClient *manager, GVariantIter iter; const gchar *interface_name; GVariant *properties; + GList *interface_added_signals, *l; + GDBusProxy *interface_proxy; g_return_if_fail (g_dbus_is_unique_name (name_owner)); + g_mutex_lock (manager->priv->lock); + + interface_added_signals = NULL; added = FALSE; + op = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path); if (op == NULL) { @@ -1405,6 +1449,7 @@ add_interfaces (GDBusObjectManagerClient *manager, NULL); added = TRUE; } + g_object_ref (op); g_variant_iter_init (&iter, ifaces_and_properties); while (g_variant_iter_next (&iter, @@ -1412,7 +1457,6 @@ add_interfaces (GDBusObjectManagerClient *manager, &interface_name, &properties)) { - GDBusProxy *interface_proxy; GError *error; GType interface_proxy_type; @@ -1476,12 +1520,23 @@ add_interfaces (GDBusObjectManagerClient *manager, _g_dbus_object_proxy_add_interface (op, interface_proxy); if (!added) - g_signal_emit_by_name (manager, "interface-added", op, interface_proxy); + interface_added_signals = g_list_append (interface_added_signals, g_object_ref (interface_proxy)); g_object_unref (interface_proxy); } g_variant_unref (properties); } + g_mutex_unlock (manager->priv->lock); + + /* now that we don't hold the lock any more, emit signals */ + for (l = interface_added_signals; l != NULL; l = l->next) + { + interface_proxy = G_DBUS_PROXY (l->data); + g_signal_emit_by_name (manager, "interface-added", op, interface_proxy); + g_object_unref (interface_proxy); + } + g_list_free (interface_added_signals); + if (added) { g_hash_table_insert (manager->priv->map_object_path_to_object_proxy, @@ -1489,6 +1544,8 @@ add_interfaces (GDBusObjectManagerClient *manager, op); g_signal_emit_by_name (manager, "object-added", op); } + g_object_unref (op); + } static void @@ -1502,12 +1559,15 @@ remove_interfaces (GDBusObjectManagerClient *manager, guint num_interfaces; guint num_interfaces_to_remove; + g_mutex_lock (manager->priv->lock); + op = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path); if (op == NULL) { g_warning ("%s: Processing InterfaceRemoved signal for path %s but no object proxy exists", G_STRLOC, object_path); + g_mutex_unlock (manager->priv->lock); goto out; } @@ -1523,11 +1583,14 @@ remove_interfaces (GDBusObjectManagerClient *manager, { g_object_ref (op); g_warn_if_fail (g_hash_table_remove (manager->priv->map_object_path_to_object_proxy, object_path)); + g_mutex_unlock (manager->priv->lock); g_signal_emit_by_name (manager, "object-removed", op); g_object_unref (op); } else { + g_object_ref (op); + g_mutex_unlock (manager->priv->lock); for (n = 0; interface_names != NULL && interface_names[n] != NULL; n++) { GDBusInterface *interface; @@ -1539,6 +1602,7 @@ remove_interfaces (GDBusObjectManagerClient *manager, g_object_unref (interface); } } + g_object_unref (op); } out: ; @@ -1619,9 +1683,11 @@ g_dbus_object_manager_client_get_object (GDBusObjectManager *_manager, GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_manager); GDBusObject *ret; + g_mutex_lock (manager->priv->lock); ret = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path); if (ret != NULL) g_object_ref (ret); + g_mutex_unlock (manager->priv->lock); return ret; } @@ -1654,8 +1720,11 @@ g_dbus_object_manager_client_get_objects (GDBusObjectManager *_manager) g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL); + g_mutex_lock (manager->priv->lock); ret = g_hash_table_get_values (manager->priv->map_object_path_to_object_proxy); g_list_foreach (ret, (GFunc) g_object_ref, NULL); + g_mutex_unlock (manager->priv->lock); + return ret; } -- 2.7.4