Commit 4e7ef619 authored by David Zeuthen's avatar David Zeuthen
Browse files

GDBusObjectManagerClient: Add locking


Signed-off-by: default avatarDavid Zeuthen <davidz@redhat.com>
parent fcefc71d
...@@ -125,6 +125,8 @@ ...@@ -125,6 +125,8 @@
struct _GDBusObjectManagerClientPrivate struct _GDBusObjectManagerClientPrivate
{ {
GMutex *lock;
GBusType bus_type; GBusType bus_type;
GDBusConnection *connection; GDBusConnection *connection;
gchar *object_path; gchar *object_path;
...@@ -212,6 +214,8 @@ g_dbus_object_manager_client_finalize (GObject *object) ...@@ -212,6 +214,8 @@ g_dbus_object_manager_client_finalize (GObject *object)
if (manager->priv->get_proxy_type_destroy_notify != NULL) if (manager->priv->get_proxy_type_destroy_notify != NULL)
manager->priv->get_proxy_type_destroy_notify (manager->priv->get_proxy_type_user_data); 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) 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); G_OBJECT_CLASS (g_dbus_object_manager_client_parent_class)->finalize (object);
} }
...@@ -568,6 +572,7 @@ g_dbus_object_manager_client_init (GDBusObjectManagerClient *manager) ...@@ -568,6 +572,7 @@ g_dbus_object_manager_client_init (GDBusObjectManagerClient *manager)
manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
G_TYPE_DBUS_OBJECT_MANAGER_CLIENT, G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
GDBusObjectManagerClientPrivate); GDBusObjectManagerClientPrivate);
manager->priv->lock = g_mutex_new ();
manager->priv->map_object_path_to_object_proxy = g_hash_table_new_full (g_str_hash, manager->priv->map_object_path_to_object_proxy = g_hash_table_new_full (g_str_hash,
g_str_equal, g_str_equal,
g_free, g_free,
...@@ -894,8 +899,12 @@ g_dbus_object_manager_client_new_for_bus_finish (GAsyncResult *res, ...@@ -894,8 +899,12 @@ g_dbus_object_manager_client_new_for_bus_finish (GAsyncResult *res,
GDBusConnection * GDBusConnection *
g_dbus_object_manager_client_get_connection (GDBusObjectManagerClient *manager) g_dbus_object_manager_client_get_connection (GDBusObjectManagerClient *manager)
{ {
GDBusConnection *ret;
g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL); 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) ...@@ -912,8 +921,12 @@ g_dbus_object_manager_client_get_connection (GDBusObjectManagerClient *manager)
const gchar * const gchar *
g_dbus_object_manager_client_get_name (GDBusObjectManagerClient *manager) 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); 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) ...@@ -930,8 +943,12 @@ g_dbus_object_manager_client_get_name (GDBusObjectManagerClient *manager)
GDBusObjectManagerClientFlags GDBusObjectManagerClientFlags
g_dbus_object_manager_client_get_flags (GDBusObjectManagerClient *manager) 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); 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) ...@@ -951,8 +968,12 @@ g_dbus_object_manager_client_get_flags (GDBusObjectManagerClient *manager)
gchar * gchar *
g_dbus_object_manager_client_get_name_owner (GDBusObjectManagerClient *manager) 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); 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, ...@@ -973,9 +994,15 @@ signal_cb (GDBusConnection *connection,
GDBusObjectProxy *object_proxy; GDBusObjectProxy *object_proxy;
GDBusInterface *interface; GDBusInterface *interface;
g_mutex_lock (manager->priv->lock);
object_proxy = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path); object_proxy = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
if (object_proxy == NULL) if (object_proxy == NULL)
{
g_mutex_unlock (manager->priv->lock);
goto out; 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)); //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, ...@@ -1062,7 +1089,8 @@ signal_cb (GDBusConnection *connection,
} }
out: out:
; if (object_proxy != NULL)
g_object_ref (object_proxy);
} }
static void static void
...@@ -1196,6 +1224,7 @@ on_notify_g_name_owner (GObject *object, ...@@ -1196,6 +1224,7 @@ on_notify_g_name_owner (GObject *object,
gchar *old_name_owner; gchar *old_name_owner;
gchar *new_name_owner; gchar *new_name_owner;
g_mutex_lock (manager->priv->lock);
old_name_owner = manager->priv->name_owner; old_name_owner = manager->priv->name_owner;
new_name_owner = g_dbus_proxy_get_name_owner (manager->priv->control_proxy); new_name_owner = g_dbus_proxy_get_name_owner (manager->priv->control_proxy);
manager->priv->name_owner = NULL; manager->priv->name_owner = NULL;
...@@ -1205,16 +1234,19 @@ on_notify_g_name_owner (GObject *object, ...@@ -1205,16 +1234,19 @@ on_notify_g_name_owner (GObject *object,
GList *l; GList *l;
GList *proxies; 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 /* 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 * the ::object-proxy-removed following is because the name owner went
* away * away
*/ */
g_object_notify (G_OBJECT (manager), "name-owner"); 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) for (l = proxies; l != NULL; l = l->next)
{ {
GDBusObjectProxy *object_proxy = G_DBUS_OBJECT_PROXY (l->data); GDBusObjectProxy *object_proxy = G_DBUS_OBJECT_PROXY (l->data);
...@@ -1226,6 +1258,10 @@ on_notify_g_name_owner (GObject *object, ...@@ -1226,6 +1258,10 @@ on_notify_g_name_owner (GObject *object,
/* nuke local filter */ /* nuke local filter */
maybe_unsubscribe_signals (manager); maybe_unsubscribe_signals (manager);
} }
else
{
g_mutex_unlock (manager->priv->lock);
}
if (new_name_owner != NULL) if (new_name_owner != NULL)
{ {
...@@ -1263,7 +1299,9 @@ on_notify_g_name_owner (GObject *object, ...@@ -1263,7 +1299,9 @@ on_notify_g_name_owner (GObject *object,
/* do the :name-owner notify *AFTER* emitting ::object-proxy-added signals - this /* 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 * 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; manager->priv->name_owner = new_name_owner;
g_mutex_unlock (manager->priv->lock);
g_object_notify (G_OBJECT (manager), "name-owner"); g_object_notify (G_OBJECT (manager), "name-owner");
} }
...@@ -1379,10 +1417,16 @@ add_interfaces (GDBusObjectManagerClient *manager, ...@@ -1379,10 +1417,16 @@ add_interfaces (GDBusObjectManagerClient *manager,
GVariantIter iter; GVariantIter iter;
const gchar *interface_name; const gchar *interface_name;
GVariant *properties; GVariant *properties;
GList *interface_added_signals, *l;
GDBusProxy *interface_proxy;
g_return_if_fail (g_dbus_is_unique_name (name_owner)); g_return_if_fail (g_dbus_is_unique_name (name_owner));
g_mutex_lock (manager->priv->lock);
interface_added_signals = NULL;
added = FALSE; added = FALSE;
op = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path); op = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
if (op == NULL) if (op == NULL)
{ {
...@@ -1405,6 +1449,7 @@ add_interfaces (GDBusObjectManagerClient *manager, ...@@ -1405,6 +1449,7 @@ add_interfaces (GDBusObjectManagerClient *manager,
NULL); NULL);
added = TRUE; added = TRUE;
} }
g_object_ref (op);
g_variant_iter_init (&iter, ifaces_and_properties); g_variant_iter_init (&iter, ifaces_and_properties);
while (g_variant_iter_next (&iter, while (g_variant_iter_next (&iter,
...@@ -1412,7 +1457,6 @@ add_interfaces (GDBusObjectManagerClient *manager, ...@@ -1412,7 +1457,6 @@ add_interfaces (GDBusObjectManagerClient *manager,
&interface_name, &interface_name,
&properties)) &properties))
{ {
GDBusProxy *interface_proxy;
GError *error; GError *error;
GType interface_proxy_type; GType interface_proxy_type;
...@@ -1476,12 +1520,23 @@ add_interfaces (GDBusObjectManagerClient *manager, ...@@ -1476,12 +1520,23 @@ add_interfaces (GDBusObjectManagerClient *manager,
_g_dbus_object_proxy_add_interface (op, interface_proxy); _g_dbus_object_proxy_add_interface (op, interface_proxy);
if (!added) 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_object_unref (interface_proxy);
} }
g_variant_unref (properties); 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) if (added)
{ {
g_hash_table_insert (manager->priv->map_object_path_to_object_proxy, g_hash_table_insert (manager->priv->map_object_path_to_object_proxy,
...@@ -1489,6 +1544,8 @@ add_interfaces (GDBusObjectManagerClient *manager, ...@@ -1489,6 +1544,8 @@ add_interfaces (GDBusObjectManagerClient *manager,
op); op);
g_signal_emit_by_name (manager, "object-added", op); g_signal_emit_by_name (manager, "object-added", op);
} }
g_object_unref (op);
} }
static void static void
...@@ -1502,12 +1559,15 @@ remove_interfaces (GDBusObjectManagerClient *manager, ...@@ -1502,12 +1559,15 @@ remove_interfaces (GDBusObjectManagerClient *manager,
guint num_interfaces; guint num_interfaces;
guint num_interfaces_to_remove; 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); op = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
if (op == NULL) if (op == NULL)
{ {
g_warning ("%s: Processing InterfaceRemoved signal for path %s but no object proxy exists", g_warning ("%s: Processing InterfaceRemoved signal for path %s but no object proxy exists",
G_STRLOC, G_STRLOC,
object_path); object_path);
g_mutex_unlock (manager->priv->lock);
goto out; goto out;
} }
...@@ -1523,11 +1583,14 @@ remove_interfaces (GDBusObjectManagerClient *manager, ...@@ -1523,11 +1583,14 @@ remove_interfaces (GDBusObjectManagerClient *manager,
{ {
g_object_ref (op); g_object_ref (op);
g_warn_if_fail (g_hash_table_remove (manager->priv->map_object_path_to_object_proxy, object_path)); 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_signal_emit_by_name (manager, "object-removed", op);
g_object_unref (op); g_object_unref (op);
} }
else else
{ {
g_object_ref (op);
g_mutex_unlock (manager->priv->lock);
for (n = 0; interface_names != NULL && interface_names[n] != NULL; n++) for (n = 0; interface_names != NULL && interface_names[n] != NULL; n++)
{ {
GDBusInterface *interface; GDBusInterface *interface;
...@@ -1539,6 +1602,7 @@ remove_interfaces (GDBusObjectManagerClient *manager, ...@@ -1539,6 +1602,7 @@ remove_interfaces (GDBusObjectManagerClient *manager,
g_object_unref (interface); g_object_unref (interface);
} }
} }
g_object_unref (op);
} }
out: out:
; ;
...@@ -1619,9 +1683,11 @@ g_dbus_object_manager_client_get_object (GDBusObjectManager *_manager, ...@@ -1619,9 +1683,11 @@ g_dbus_object_manager_client_get_object (GDBusObjectManager *_manager,
GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_manager); GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_manager);
GDBusObject *ret; GDBusObject *ret;
g_mutex_lock (manager->priv->lock);
ret = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path); ret = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
if (ret != NULL) if (ret != NULL)
g_object_ref (ret); g_object_ref (ret);
g_mutex_unlock (manager->priv->lock);
return ret; return ret;
} }
...@@ -1654,8 +1720,11 @@ g_dbus_object_manager_client_get_objects (GDBusObjectManager *_manager) ...@@ -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_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); ret = g_hash_table_get_values (manager->priv->map_object_path_to_object_proxy);
g_list_foreach (ret, (GFunc) g_object_ref, NULL); g_list_foreach (ret, (GFunc) g_object_ref, NULL);
g_mutex_unlock (manager->priv->lock);
return ret; return ret;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment