[glib: 2/4] gdbusobjectmanagerclient: Call GetManagedObjects async




commit c548ac0796cbc208751d0eb6761626f0091faf26
Author: Guido Günther <agx sigxcpu org>
Date:   Wed May 26 21:14:39 2021 +0200

    gdbusobjectmanagerclient: Call GetManagedObjects async
    
    This helps to void deadlocks when two processes call interfaces on each
    other one of them being org.freedesktop.DBus.ObjectManager.
    
    Signed-off-by: Guido Günther <agx sigxcpu org>

 gio/gdbusobjectmanagerclient.c | 95 ++++++++++++++++++++++++++----------------
 1 file changed, 60 insertions(+), 35 deletions(-)
---
diff --git a/gio/gdbusobjectmanagerclient.c b/gio/gdbusobjectmanagerclient.c
index 80b716bc7..bc3fd3d5f 100644
--- a/gio/gdbusobjectmanagerclient.c
+++ b/gio/gdbusobjectmanagerclient.c
@@ -1259,6 +1259,57 @@ weak_ref_free (GWeakRef *weak_ref)
   g_free (weak_ref);
 }
 
+static void
+on_get_managed_objects_finish (GObject      *source,
+                               GAsyncResult *result,
+                               gpointer      user_data)
+{
+
+  GDBusProxy *proxy = G_DBUS_PROXY (source);
+  GWeakRef *manager_weak = user_data;
+  GDBusObjectManagerClient *manager;
+  GError *error = NULL;
+  GVariant *value = NULL;
+  gchar *new_name_owner = NULL;
+
+  value = g_dbus_proxy_call_finish (proxy, result, &error);
+
+  manager = G_DBUS_OBJECT_MANAGER_CLIENT (g_weak_ref_get (manager_weak));
+  /* Manager got disposed, nothing to do */
+  if (manager == NULL)
+    {
+      goto out;
+    }
+
+  new_name_owner = g_dbus_proxy_get_name_owner (manager->priv->control_proxy);
+  if (value == NULL)
+    {
+      maybe_unsubscribe_signals (manager);
+      g_warning ("Error calling GetManagedObjects() when name owner %s for name %s came back: %s",
+                 new_name_owner,
+                 manager->priv->name,
+                 error->message);
+    }
+  else
+    {
+      process_get_all_result (manager, value, new_name_owner);
+    }
+
+  /* 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 = g_steal_pointer (&new_name_owner);
+  g_mutex_unlock (&manager->priv->lock);
+  g_object_notify (G_OBJECT (manager), "name-owner");
+
+  g_object_unref (manager);
+ out:
+  g_clear_error (&error);
+  g_clear_pointer (&value, g_variant_unref);
+  weak_ref_free (manager_weak);
+}
+
 static void
 on_notify_g_name_owner (GObject    *object,
                         GParamSpec *pspec,
@@ -1313,46 +1364,20 @@ on_notify_g_name_owner (GObject    *object,
 
   if (new_name_owner != NULL)
     {
-      GError *error;
-      GVariant *value;
-
       //g_debug ("repopulating for %s", new_name_owner);
 
-      /* TODO: do this async! */
       subscribe_signals (manager,
                          new_name_owner);
-      error = NULL;
-      value = g_dbus_proxy_call_sync (manager->priv->control_proxy,
-                                      "GetManagedObjects",
-                                      NULL, /* parameters */
-                                      G_DBUS_CALL_FLAGS_NONE,
-                                      -1,
-                                      NULL,
-                                      &error);
-      if (value == NULL)
-        {
-          maybe_unsubscribe_signals (manager);
-          g_warning ("Error calling GetManagedObjects() when name owner %s for name %s came back: %s",
-                     new_name_owner,
-                     manager->priv->name,
-                     error->message);
-          g_error_free (error);
-        }
-      else
-        {
-          process_get_all_result (manager, value, new_name_owner);
-          g_variant_unref (value);
-        }
-
-      /* 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");
-
+      g_dbus_proxy_call (manager->priv->control_proxy,
+                         "GetManagedObjects",
+                         NULL, /* parameters */
+                         G_DBUS_CALL_FLAGS_NONE,
+                         -1,
+                         NULL,
+                         on_get_managed_objects_finish,
+                         weak_ref_new (G_OBJECT (manager)));
     }
+  g_free (new_name_owner);
   g_free (old_name_owner);
   g_object_unref (manager);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]