[gvfs] MTP: Fix race between on_uevent and do_unmount.



commit 2ad82f2751b4a13dbcf8e7373a386019982bb43b
Author: Philip Langdale <philipl overt org>
Date:   Wed Jan 23 09:07:22 2013 -0800

    MTP: Fix race between on_uevent and do_unmount.
    
    I've never seen this happen personally, but an Ubuntu bug reported
    that on_uevent fired after the gudev client had been finalized, so
    it must be possible to race between an explicit unmount and
    physically unplugging a device. I made a brief attempt to reproduce
    this but couldn't.
    
    In any case, it's easy enough to protect against by taking a few
    measures:
    
    1) Explicitly disconnect the signal handler before unref'ing the
       gudev client.
    2) Use g_signal_connect_object to keep the backend alive enough
       for on_uevent to complete.
    3) NULL out the dev_path so that if we end up in on_uevent after
       do_unmount has cleared the dev_path, the compare will fail
       gracefully.

 daemon/gvfsbackendmtp.c |    8 ++++++--
 daemon/gvfsbackendmtp.h |    1 +
 2 files changed, 7 insertions(+), 2 deletions(-)
---
diff --git a/daemon/gvfsbackendmtp.c b/daemon/gvfsbackendmtp.c
index 121115a..a39e4d1 100644
--- a/daemon/gvfsbackendmtp.c
+++ b/daemon/gvfsbackendmtp.c
@@ -449,7 +449,9 @@ do_mount (GVfsBackend *backend,
   }
   op_backend->dev_path = dev_path;
 
-  g_signal_connect (op_backend->gudev_client, "uevent", G_CALLBACK (on_uevent), op_backend);
+  op_backend->on_uevent_id =
+    g_signal_connect_object (op_backend->gudev_client, "uevent",
+                             G_CALLBACK (on_uevent), op_backend, 0);
 
   LIBMTP_Init ();
 
@@ -497,8 +499,10 @@ do_unmount (GVfsBackend *backend, GVfsJobUnmount *job,
   g_atomic_int_set (&op_backend->unmount_started, TRUE);
 
   g_source_remove (op_backend->hb_id);
+  g_signal_handler_disconnect (op_backend->gudev_client,
+                               op_backend->on_uevent_id);
   g_object_unref (op_backend->gudev_client);
-  g_free (op_backend->dev_path);
+  g_clear_pointer (&op_backend->dev_path, g_free);
   LIBMTP_Release_Device (op_backend->device);
 
   g_mutex_unlock (&op_backend->mutex);
diff --git a/daemon/gvfsbackendmtp.h b/daemon/gvfsbackendmtp.h
index 9dbaa0c..4137b65 100644
--- a/daemon/gvfsbackendmtp.h
+++ b/daemon/gvfsbackendmtp.h
@@ -47,6 +47,7 @@ struct _GVfsBackendMtp
 
 #ifdef HAVE_GUDEV
   GUdevClient *gudev_client;
+  gulong on_uevent_id;
 #endif
 
   GMutex mutex;



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