[gvfs] dnssd: Prevent crash when resolving service



commit 3384af829c31b36e8b5ead87427ef6a61b89f11d
Author: Ross Lagerwall <rosslagerwall gmail com>
Date:   Sun Mar 8 00:42:18 2015 +0000

    dnssd: Prevent crash when resolving service
    
    AvahiClient appears to require that avahi_service_resolver_new is
    invoked from the same thread to which its poll function is bound
    otherwise it can crash with a callback running while
    avahi_service_resolver_new is still busy.
    
    To fix this, always run avahi_service_resolver_new from the main loop.
    To simplify the code, any errors from the function are ignored for now.
    
    This crash could be reproduced 100% of the time by trying to mount
    dav+sd (via gnome-user-share) in a single-CPU VM.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=629345

 common/gvfsdnssdresolver.c |   58 ++++++++++++++-----------------------------
 1 files changed, 19 insertions(+), 39 deletions(-)
---
diff --git a/common/gvfsdnssdresolver.c b/common/gvfsdnssdresolver.c
index e70e57f..339a763 100644
--- a/common/gvfsdnssdresolver.c
+++ b/common/gvfsdnssdresolver.c
@@ -23,6 +23,7 @@
 /*
  * TODO: - locking
  *       - cancellation
+ *       - error handling
  *       - get rid of g_main_loop (bug 555436#c32)
  */
 
@@ -100,8 +101,7 @@ static gboolean avahi_initialized = FALSE;
 static void free_global_avahi_client (void);
 static AvahiClient *get_global_avahi_client (GError **error);
 
-static gboolean ensure_avahi_resolver (GVfsDnsSdResolver  *resolver,
-                                       GError            **error);
+static void ensure_avahi_resolver (GVfsDnsSdResolver  *resolver);
 
 static void service_resolver_cb (AvahiServiceResolver   *resolver,
                                  AvahiIfIndex            interface,
@@ -139,7 +139,7 @@ remove_client_from_resolver (GVfsDnsSdResolver *resolver)
 static void
 add_client_to_resolver (GVfsDnsSdResolver *resolver)
 {
-  ensure_avahi_resolver (resolver, NULL);
+  ensure_avahi_resolver (resolver);
 }
 
 /* Callback for state changes on the Client */
@@ -217,23 +217,13 @@ get_global_avahi_client (GError **error)
   return global_client;
 }
 
-
 static gboolean
-ensure_avahi_resolver (GVfsDnsSdResolver  *resolver,
-                       GError            **error)
+start_avahi_resolver (gpointer user_data)
 {
+  GVfsDnsSdResolver *resolver = G_VFS_DNS_SD_RESOLVER (user_data);
   AvahiClient *avahi_client;
-  gboolean ret;
-
-  ret = FALSE;
 
-  if (resolver->avahi_resolver != NULL)
-    {
-      ret = TRUE;
-      goto out;
-    }
-
-  avahi_client = get_global_avahi_client (error);
+  avahi_client = get_global_avahi_client (NULL);
   if (avahi_client == NULL)
     goto out;
 
@@ -247,20 +237,19 @@ ensure_avahi_resolver (GVfsDnsSdResolver  *resolver,
                                                          0, /* AvahiLookupFlags */
                                                          service_resolver_cb,
                                                          resolver);
-  if (resolver->avahi_resolver == NULL)
-    {
-      g_set_error (error,
-                   G_IO_ERROR,
-                   G_IO_ERROR_FAILED,
-                   _("Error creating Avahi resolver: %s"),
-                   avahi_strerror (avahi_client_errno (avahi_client)));
-      goto out;
-    }
-
-  ret = TRUE;
 
 out:
-  return ret;
+  g_object_unref (resolver);
+  return FALSE;
+}
+
+static void
+ensure_avahi_resolver (GVfsDnsSdResolver  *resolver)
+{
+  if (resolver->avahi_resolver != NULL)
+    return;
+
+  g_idle_add (start_avahi_resolver, g_object_ref (resolver));
 }
 
 static void
@@ -469,7 +458,7 @@ g_vfs_dns_sd_resolver_constructed (GObject *object)
                                                          resolver->domain);
 
   /* start resolving immediately */
-  ensure_avahi_resolver (resolver, NULL);
+  ensure_avahi_resolver (resolver);
 
   resolvers = g_list_prepend (resolvers, resolver);
 
@@ -1175,7 +1164,6 @@ g_vfs_dns_sd_resolver_resolve (GVfsDnsSdResolver  *resolver,
 {
   ResolveData *data;
   GSimpleAsyncResult *simple;
-  GError *error;
 
   g_return_if_fail (G_VFS_IS_DNS_SD_RESOLVER (resolver));
 
@@ -1193,15 +1181,7 @@ g_vfs_dns_sd_resolver_resolve (GVfsDnsSdResolver  *resolver,
       goto out;
     }
 
-  error = NULL;
-  if (!ensure_avahi_resolver (resolver, &error))
-    {
-      g_simple_async_result_set_from_error (simple, error);
-      g_simple_async_result_complete (simple);
-      g_object_unref (simple);
-      g_error_free (error);
-      goto out;
-    }
+  ensure_avahi_resolver (resolver);
 
   data = g_new0 (ResolveData, 1);
   data->resolver = resolver;


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