[gvfs] afc: Cleanup force-unmount idle on finalize
- From: Christophe Fergeau <teuf src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs] afc: Cleanup force-unmount idle on finalize
- Date: Fri, 3 Jul 2015 11:58:01 +0000 (UTC)
commit 63e3d144784eefe112de6b4e821664ebef94b0ab
Author: Christophe Fergeau <cfergeau redhat com>
Date: Wed Jul 1 18:29:56 2015 +0200
afc: Cleanup force-unmount idle on finalize
When GvfsBackendAfc is finalized, if we have a pending idle for a force
unmount, we need to remove it as by the time it runs, the GvfsBackendAfc
it's acting on will no longer be valid.
This fixes https://bugzilla.gnome.org/show_bug.cgi?id=751537 which can
be reproduced by plugging an iDevice, unmounting it in Nautilus, and
quickly unplugging it right after clicking on the eject icon.
daemon/gvfsbackendafc.c | 32 ++++++++++++++++++++++++++++++--
1 files changed, 30 insertions(+), 2 deletions(-)
---
diff --git a/daemon/gvfsbackendafc.c b/daemon/gvfsbackendafc.c
index 22bab16..1c041a8 100644
--- a/daemon/gvfsbackendafc.c
+++ b/daemon/gvfsbackendafc.c
@@ -87,6 +87,8 @@ struct _GVfsBackendAfc {
idevice_t dev;
afc_client_t afc_cli; /* for ACCESS_MODE_AFC */
+ guint force_umount_id;
+
/* for ACCESS_MODE_HOUSE_ARREST */
GHashTable *apps; /* hash table of AppInfo */
instproxy_client_t inst;
@@ -353,6 +355,9 @@ force_umount_idle (gpointer user_data)
g_vfs_backend_force_unmount (G_VFS_BACKEND(afc_backend));
+ afc_backend->force_umount_id = 0;
+ g_object_unref (afc_backend);
+
return G_SOURCE_REMOVE;
}
@@ -372,9 +377,20 @@ _idevice_event_cb (const idevice_event_t *event, void *user_data)
g_print ("Shutting down AFC backend for device uuid %s\n", afc_backend->uuid);
- /* idevice_event_unsubscribe() will terminate the thread _idevice_event_cb
+ /* This might happen if the user manages to unplug/replug/unplug the same device
+ * before the idle runs
+ */
+ if (afc_backend->force_umount_id != 0)
+ {
+ g_print ("AFC device with uuid %s is already being removed",
+ afc_backend->uuid);
+ return;
+ }
+
+ /* idevice_event_unsubscribe () will terminate the thread _idevice_event_cb
* is running in, so we need to call back into our main loop */
- g_idle_add(force_umount_idle, afc_backend);
+ afc_backend->force_umount_id = g_idle_add (force_umount_idle,
+ g_object_ref (afc_backend));
}
static gboolean
@@ -759,6 +775,8 @@ g_vfs_backend_afc_unmount (GVfsBackend *backend,
{
GVfsBackendAfc *self;
+ idevice_event_unsubscribe ();
+
/* FIXME: check on G_MOUNT_UNMOUNT_FORCE flag */
self = G_VFS_BACKEND_AFC (backend);
g_vfs_backend_afc_close_connection (self);
@@ -2722,6 +2740,16 @@ g_vfs_backend_afc_finalize (GObject *obj)
self = G_VFS_BACKEND_AFC(obj);
g_vfs_backend_afc_close_connection (self);
+ idevice_event_unsubscribe ();
+ /* After running idevice_event_unsubscribe() we won't get any new event
+ * notifications, but we are also guaranteed that currently running event
+ * callbacks will have completed, so no other thread is going to requeue
+ * an idle after we removed it */
+ if (self->force_umount_id != 0) {
+ g_source_remove(self->force_umount_id);
+ self->force_umount_id = 0;
+ }
+
if (G_OBJECT_CLASS(g_vfs_backend_afc_parent_class)->finalize)
(*G_OBJECT_CLASS(g_vfs_backend_afc_parent_class)->finalize) (obj);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]