GNOME Bugzilla – Bug 733694
mount cache is not invalidated promptly (repeated mount + unmount fails)
Last modified: 2014-07-25 06:46:16 UTC
Steps to reproduce: * mount a SMB volume by its UNC path (\\machine\share) via - transforming the UNC path to a URI - g_file_new_for_uri ("smb://machine/share") - g_file_mount_enclosing_volume() * unmount the volume by its UNC path by - transforming the UNC path to a URI again - g_file_new_for_uri() - g_file_find_enclosing_mount() - g_mount_unmount_with_operation() * repeat Expected result: * each unmount succeeds Actual result: * second unmount fails: Unmount error: No such interface 'org.gtk.vfs.Mount' on object at path /org/gtk/vfs/mount/1
Analysis: g_daemon_file_find_enclosing_mount() calls _g_daemon_vfs_get_mount_info_sync() which looks up the GMountInfo in the_vfs->mount_cache. Entries in the_vfs->mount_cache are only invalidated when the backend process dies, at which point each entry with a matching "dbus_id" (D-Bus unique name) is invalidated. However, in our test case, the first mount starts one backend process, say :1.4. The second mount starts another, say :1.6, but the one from the first mount is still present on D-Bus; this means that the GMountInfo { ":1.4", "/org/gtk/vfs/mount/1", etc. } is still present in the mount cache. When the second unmount looks for the enclosing mount, it finds { ":1.4", "/org/gtk/vfs/mount/1", etc. } and does not make a new call into the MountTracker. (If it did, it would eventually get { ":1.6", "/org/gtk/vfs/mount/1", etc. } and everything would be great.) As a result, we send the Unmount() call to :1.4, and it fails.
Thoughts about restoring cache coherence: In the particular project where I'm encountering this, we're interacting with GIO from a non-main thread: so I can't necessarily guarantee that there's going to be anything that can receive Mounted and Unmounted signals, and even if there was, I wouldn't be able to guarantee that the Mounted or Unmounted signal would be processed by the signal-receiving thread before the mount/unmount thread re-mounts the share. The best idea I've had so far is for Unmount() to invalidate the cache before it returns, and this seems to fix our test case. If two threads race with each other to mount/unmount shares, they can expect to lose anyway; so we only need to care about the case where Unmount() and the following mount operation have a happens-after relationship, either by being in the same thread or having some sort of lock. Mount should perhaps invalidate the cache too, but I'm not particularly familiar with gvfs, so I don't know which code path(s) I need to cover.
Created attachment 281631 [details] [review] GDaemonMount: invalidate mount cache whenever we unmount a mount
Created attachment 281632 [details] test case I realise this is far from idiomatic; I didn't write it. It's simplified from code that is constrained to implement a pre-existing API, and has a very limited ability to rely on GIO conventions elsewhere in the process.
*** This bug has been marked as a duplicate of bug 731077 ***