registry: safely destroy proxy when its initial augment is still in progress

... in case the global is removed from the registry before
the initial augment completes
This commit is contained in:
George Kiagiadakis
2020-02-14 16:37:28 +02:00
parent 269b9e1998
commit 813351bcdf
3 changed files with 34 additions and 8 deletions

View File

@@ -525,6 +525,7 @@ wp_global_rm_flag (WpGlobal *global, guint rm_flag)
if (global->flags == 0 && global->proxy) { if (global->flags == 0 && global->proxy) {
if (reg) if (reg)
wp_registry_notify_rm_object (reg, global->proxy); wp_registry_notify_rm_object (reg, global->proxy);
wp_proxy_destroy (global->proxy);
g_clear_object (&global->proxy); g_clear_object (&global->proxy);
} }
} }
@@ -902,10 +903,16 @@ static void
on_proxy_ready (GObject * proxy, GAsyncResult * res, gpointer data) on_proxy_ready (GObject * proxy, GAsyncResult * res, gpointer data)
{ {
g_autoptr (WpObjectManager) self = WP_OBJECT_MANAGER (data); g_autoptr (WpObjectManager) self = WP_OBJECT_MANAGER (data);
g_autoptr (GError) error = NULL;
if (wp_proxy_augment_finish (WP_PROXY (proxy), res, &error)) {
g_ptr_array_add (self->objects, proxy); g_ptr_array_add (self->objects, proxy);
g_signal_emit (self, signals[SIGNAL_OBJECT_ADDED], 0, proxy); g_signal_emit (self, signals[SIGNAL_OBJECT_ADDED], 0, proxy);
schedule_emit_objects_changed (self); schedule_emit_objects_changed (self);
} else {
g_message ("WpObjectManager:%p proxy augment failed: %s", self,
error->message);
}
} }
static void static void

View File

@@ -122,6 +122,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (WpGlobal, wp_global_unref)
/* proxy */ /* proxy */
void wp_proxy_destroy (WpProxy *self);
void wp_proxy_set_pw_proxy (WpProxy * self, struct pw_proxy * proxy); void wp_proxy_set_pw_proxy (WpProxy * self, struct pw_proxy * proxy);
void wp_proxy_set_feature_ready (WpProxy * self, WpProxyFeatures feature); void wp_proxy_set_feature_ready (WpProxy * self, WpProxyFeatures feature);

View File

@@ -70,18 +70,18 @@ static void
proxy_event_destroy (void *data) proxy_event_destroy (void *data)
{ {
/* hold a reference to the proxy because unref-ing the tasks might /* hold a reference to the proxy because unref-ing the tasks might
destroy the proxy, in case the core is no longer holding a reference */ destroy the proxy, in case the registry is no longer holding a reference */
g_autoptr (WpProxy) self = g_object_ref (WP_PROXY (data)); g_autoptr (WpProxy) self = g_object_ref (WP_PROXY (data));
WpProxyPrivate *priv = wp_proxy_get_instance_private (self); WpProxyPrivate *priv = wp_proxy_get_instance_private (self);
GHashTableIter iter; GHashTableIter iter;
GTask *task; GTask *task;
g_debug ("%s:%p destroyed pw_proxy %p (%s; %u)", g_debug ("%s:%p destroyed pw_proxy %p (%u)",
G_OBJECT_TYPE_NAME (self), self, priv->pw_proxy, G_OBJECT_TYPE_NAME (self), self, priv->pw_proxy,
priv->global ? "global" : "not global", priv->global ? priv->global->id : pw_proxy_get_bound_id (priv->pw_proxy));
wp_proxy_get_bound_id (self));
priv->pw_proxy = NULL;
spa_hook_remove (&priv->listener);
priv->pw_proxy = NULL;
g_signal_emit (self, wp_proxy_signals[SIGNAL_PW_PROXY_DESTROYED], 0); g_signal_emit (self, wp_proxy_signals[SIGNAL_PW_PROXY_DESTROYED], 0);
/* Return error if the pw_proxy destruction happened while the async /* Return error if the pw_proxy destruction happened while the async
@@ -358,6 +358,18 @@ wp_proxy_class_init (WpProxyClass * klass)
G_TYPE_INT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_POINTER); G_TYPE_INT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_POINTER);
} }
void
wp_proxy_destroy (WpProxy *self)
{
WpProxyPrivate *priv;
g_return_if_fail (WP_IS_PROXY (self));
priv = wp_proxy_get_instance_private (self);
if (priv->pw_proxy)
pw_proxy_destroy (priv->pw_proxy);
}
void void
wp_proxy_augment (WpProxy * self, wp_proxy_augment (WpProxy * self,
WpProxyFeatures ft_wanted, GCancellable * cancellable, WpProxyFeatures ft_wanted, GCancellable * cancellable,
@@ -416,6 +428,10 @@ wp_proxy_set_feature_ready (WpProxy * self, WpProxyFeatures feature)
g_object_notify (G_OBJECT (self), "features"); g_object_notify (G_OBJECT (self), "features");
/* hold a reference to the proxy because unref-ing the tasks might
destroy the proxy, in case the registry is no longer holding a reference */
g_object_ref (self);
/* return from the task if all the wanted features are now ready */ /* return from the task if all the wanted features are now ready */
for (i = priv->augment_tasks->len; i > 0; i--) { for (i = priv->augment_tasks->len; i > 0; i--) {
GTask *task = g_ptr_array_index (priv->augment_tasks, i - 1); GTask *task = g_ptr_array_index (priv->augment_tasks, i - 1);
@@ -427,6 +443,8 @@ wp_proxy_set_feature_ready (WpProxy * self, WpProxyFeatures feature)
g_ptr_array_remove_index_fast (priv->augment_tasks, i - 1); g_ptr_array_remove_index_fast (priv->augment_tasks, i - 1);
} }
} }
g_object_unref (self);
} }
/** /**