From 340b52fbeec4ae2ba7f8f70d270efc6440ec91fe Mon Sep 17 00:00:00 2001 From: George Kiagiadakis <george.kiagiadakis@collabora.com> Date: Tue, 17 Sep 2019 16:19:13 +0300 Subject: [PATCH] proxy: fix crash that happens when a client exits very quickly after starting This is very easy to reproduce when the pipewire-alsa integration is installed and you do 'arecord -l'; the alsa plugin connects and disconnects again before the proxy is ready. In this case we have to skip remote-global-added and we also have to be careful with the references: the global-removed callback is called earlier, so the core's reference to the proxy is gone and the GTask is the only thing holding a reference to the proxy. When we unref the GTask, the proxy is also unrefed, so we have to keep an additional reference in order to avoid crashing when accessing the hash table below. --- lib/wp/core.c | 1 + lib/wp/proxy.c | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/wp/core.c b/lib/wp/core.c index c114936b..d065741c 100644 --- a/lib/wp/core.c +++ b/lib/wp/core.c @@ -138,6 +138,7 @@ on_proxy_ready (GObject * obj, GAsyncResult * res, gpointer data) if (!wp_proxy_augment_finish (proxy, res, &error)) { g_warning ("Failed to augment WpProxy (%p): %s", obj, error->message); + return; } g_signal_emit (self, signals[SIGNAL_REMOTE_GLOBAL_ADDED], diff --git a/lib/wp/proxy.c b/lib/wp/proxy.c index 16c8b205..876a721d 100644 --- a/lib/wp/proxy.c +++ b/lib/wp/proxy.c @@ -130,7 +130,9 @@ wp_proxy_find_quark_for_type (guint32 type) static void proxy_event_destroy (void *data) { - WpProxy *self = WP_PROXY (data); + /* 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 */ + g_autoptr (WpProxy) self = g_object_ref (WP_PROXY (data)); WpProxyPrivate *priv = wp_proxy_get_instance_private (self); GHashTableIter iter; GTask *task; @@ -144,7 +146,7 @@ proxy_event_destroy (void *data) if (priv->task) { g_task_return_new_error (priv->task, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED, - "pipewire node proxy destroyed before finishing"); + "pipewire proxy destroyed before finishing"); g_clear_object (&priv->task); } @@ -152,7 +154,7 @@ proxy_event_destroy (void *data) while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &task)) { g_task_return_new_error (task, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED, - "pipewire node proxy destroyed before finishing"); + "pipewire proxy destroyed before finishing"); g_hash_table_iter_remove (&iter); } } @@ -218,9 +220,9 @@ wp_proxy_finalize (GObject * object) g_debug ("%s:%p destroyed (global %u; pw_proxy %p)", G_OBJECT_TYPE_NAME (object), object, priv->global_id, priv->pw_proxy); + g_clear_pointer (&priv->pw_proxy, pw_proxy_destroy); g_clear_object (&priv->task); g_clear_pointer (&priv->global_props, wp_properties_unref); - g_clear_pointer (&priv->pw_proxy, pw_proxy_destroy); g_weak_ref_clear (&priv->core); g_clear_pointer (&priv->async_tasks, g_hash_table_unref); -- GitLab