summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Holy <oholy@redhat.com>2016-07-29 12:48:19 +0200
committerOndrej Holy <oholy@redhat.com>2016-07-29 13:55:37 +0200
commit6c1124d7d48e680378f353c993c311818dcdbf0d (patch)
tree021e769e8d4ab0fa5393401a4fec10175aa11403
parentb2be2f0df6e39b8898a8437c8073cb9132ca2d2b (diff)
downloadgvfs-6c1124d7d48e680378f353c993c311818dcdbf0d.tar.gz
dnssd: Fix crashes when mount failed
Mount operation might fail if you run multiple mount operations concurrently. Backend memory is released consequently. Unfortunatelly AvahiServiceResolvers are not freed and thus resolve_callback might be called after backend finalize, which causes segmentation faults. This patch fixes this and also some other memory leaks. https://bugzilla.gnome.org/show_bug.cgi?id=631023
-rw-r--r--daemon/gvfsbackenddnssd.c29
1 files changed, 17 insertions, 12 deletions
diff --git a/daemon/gvfsbackenddnssd.c b/daemon/gvfsbackenddnssd.c
index e51fbba6..344ef830 100644
--- a/daemon/gvfsbackenddnssd.c
+++ b/daemon/gvfsbackenddnssd.c
@@ -131,6 +131,7 @@ struct _GVfsBackendDnsSd
GList *files; /* list of LinkFiles */
GList *browsers;
+ GList *resolvers;
};
typedef struct _GVfsBackendDnsSd GVfsBackendDnsSd;
@@ -566,19 +567,19 @@ resolve_callback (AvahiServiceResolver *r,
char *path;
if (event == AVAHI_RESOLVER_FAILURE)
- return;
-
+ goto out;
+
/* Link-local ipv6 address, can't make a uri from this, ignore */
if (address->proto == AVAHI_PROTO_INET6 &&
address->data.ipv6.address[0] == 0xfe &&
address->data.ipv6.address[1] == 0x80)
- return;
-
+ goto out;
+
file = lookup_link_file_by_name_and_type (backend,
name, type);
if (file != NULL)
- return;
+ goto out;
file = link_file_new (name, type, domain, host_name, protocol,
address, port, txt);
@@ -591,6 +592,10 @@ resolve_callback (AvahiServiceResolver *r,
path,
NULL);
g_free (path);
+
+ out:
+ backend->resolvers = g_list_remove (backend->resolvers, r);
+ avahi_service_resolver_free (r);
}
static void
@@ -617,18 +622,15 @@ browse_callback (AvahiServiceBrowser *b,
case AVAHI_BROWSER_NEW:
client = get_global_avahi_client ();
-
- /* We ignore the returned resolver object. In the callback
- function we free it. If the server is terminated before
- the callback function is called the server will free
- the resolver for us. */
-
+
sr = avahi_service_resolver_new (client, interface, protocol,
name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, backend);
if (sr == NULL)
g_warning ("Failed to resolve service name '%s': %s\n", name, avahi_strerror (avahi_client_errno (client)));
-
+ else
+ backend->resolvers = g_list_prepend (backend->resolvers, sr);
+
break;
case AVAHI_BROWSER_REMOVE:
@@ -799,6 +801,9 @@ g_vfs_backend_dns_sd_finalize (GObject *object)
dnssd_backends = g_list_remove (dnssd_backends, backend);
+ remove_browsers (backend);
+ g_list_free_full (backend->resolvers, (GDestroyNotify)avahi_service_resolver_free);
+
if (backend->mount_spec)
g_mount_spec_unref (backend->mount_spec);