mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-11-04 10:08:56 +01:00 
			
		
		
		
	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>
This commit is contained in:
		@@ -1259,6 +1259,57 @@ weak_ref_free (GWeakRef *weak_ref)
 | 
				
			|||||||
  g_free (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
 | 
					static void
 | 
				
			||||||
on_notify_g_name_owner (GObject    *object,
 | 
					on_notify_g_name_owner (GObject    *object,
 | 
				
			||||||
                        GParamSpec *pspec,
 | 
					                        GParamSpec *pspec,
 | 
				
			||||||
@@ -1313,46 +1364,20 @@ on_notify_g_name_owner (GObject    *object,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if (new_name_owner != NULL)
 | 
					  if (new_name_owner != NULL)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      GError *error;
 | 
					 | 
				
			||||||
      GVariant *value;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      //g_debug ("repopulating for %s", new_name_owner);
 | 
					      //g_debug ("repopulating for %s", new_name_owner);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      /* TODO: do this async! */
 | 
					 | 
				
			||||||
      subscribe_signals (manager,
 | 
					      subscribe_signals (manager,
 | 
				
			||||||
                         new_name_owner);
 | 
					                         new_name_owner);
 | 
				
			||||||
      error = NULL;
 | 
					      g_dbus_proxy_call (manager->priv->control_proxy,
 | 
				
			||||||
      value = g_dbus_proxy_call_sync (manager->priv->control_proxy,
 | 
					                         "GetManagedObjects",
 | 
				
			||||||
                                      "GetManagedObjects",
 | 
					                         NULL, /* parameters */
 | 
				
			||||||
                                      NULL, /* parameters */
 | 
					                         G_DBUS_CALL_FLAGS_NONE,
 | 
				
			||||||
                                      G_DBUS_CALL_FLAGS_NONE,
 | 
					                         -1,
 | 
				
			||||||
                                      -1,
 | 
					                         NULL,
 | 
				
			||||||
                                      NULL,
 | 
					                         on_get_managed_objects_finish,
 | 
				
			||||||
                                      &error);
 | 
					                         weak_ref_new (G_OBJECT (manager)));
 | 
				
			||||||
      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_free (new_name_owner);
 | 
				
			||||||
  g_free (old_name_owner);
 | 
					  g_free (old_name_owner);
 | 
				
			||||||
  g_object_unref (manager);
 | 
					  g_object_unref (manager);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user