From 396216f71abf6907efd1383ca0d1a597918cd83d Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Thu, 11 Oct 2018 17:47:59 +0200 Subject: [PATCH] daemon: Prevent spawning new daemons if outgoing operation exists A new daemon is always spawned if MountLocation method (or LookupMount for automounted) is called and the respective mount isn't registered yet. This is not usually an issue, because the redundant daemons are consequently terminated. However, this is a problem if mount operations hang for some reason. This may happen e.g. with trash backend due to stale NFS mounts. Consequently, new and new daemons are spawned which may lead to system failures due to lack of system resources. See the following downstream bug report: https://bugzilla.redhat.com/show_bug.cgi?id=1632960 Let's fix that behavior simply by preventing spawning of new daemons if respective outgoing mount operations exist. https://gitlab.gnome.org/GNOME/gvfs/merge_requests/19 --- daemon/mount.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/daemon/mount.c b/daemon/mount.c index e242666d..33cae597 100644 --- a/daemon/mount.c +++ b/daemon/mount.c @@ -73,6 +73,7 @@ typedef void (*MountCallback) (VfsMountable *mountable, static GList *mountables = NULL; static GList *mounts = NULL; +static GList *ongoing = NULL; static gboolean fuse_available; @@ -253,6 +254,7 @@ typedef struct { char *obj_path; gboolean spawned; GVfsDBusSpawner *spawner; + GList *pending; /* MountData */ } MountData; static void spawn_mount (MountData *data); @@ -264,6 +266,7 @@ mount_data_free (MountData *data) g_mount_spec_unref (data->mount_spec); g_free (data->obj_path); g_clear_object (&data->spawner); + g_list_free_full (data->pending, (GDestroyNotify) mount_data_free); g_free (data); } @@ -271,7 +274,17 @@ mount_data_free (MountData *data) static void mount_finish (MountData *data, GError *error) { + GList *l; + + ongoing = g_list_remove (ongoing, data); + data->callback (data->mountable, error, data->user_data); + for (l = data->pending; l != NULL; l = l->next) + { + MountData *pending_data = l->data; + pending_data->callback (pending_data->mountable, error, pending_data->user_data); + } + mount_data_free (data); } @@ -493,6 +506,7 @@ mountable_mount (VfsMountable *mountable, gpointer user_data) { MountData *data; + GList *l; data = g_new0 (MountData, 1); data->automount = automount; @@ -502,6 +516,18 @@ mountable_mount (VfsMountable *mountable, data->callback = callback; data->user_data = user_data; + for (l = ongoing; l != NULL; l = l->next) + { + MountData *ongoing_data = l->data; + if (g_mount_spec_equal (ongoing_data->mount_spec, mount_spec)) + { + ongoing_data->pending = g_list_append (ongoing_data->pending, data); + return; + } + } + + ongoing = g_list_append (ongoing, data); + if (mountable->dbus_name == NULL) spawn_mount (data); else -- 2.20.1