GNOME Bugzilla – Bug 749317
Creating a gvfs file monitor appears sync but is really async
Last modified: 2015-10-09 11:56:49 UTC
Created attachment 303309 [details] reproducer See the attached reproducer, which is a slightly modified version of the one for bug 749314. I create a GFileMonitor for trash:// and then trash a file in an idle callback straight away. The callback is not called with 2.45, but with 2.44 it is. If I do it with a timeout (2ms is fine), then it is called.
From a quick read of gvfs it looks like creating a file monitor is done asynchronously and you don't start receiving events until some time after the monitor has been created and returned to you. GFileMonitor * g_daemon_file_monitor_new (const char *remote_id, const char *remote_obj_path) { GDaemonFileMonitor* daemon_monitor; daemon_monitor = g_object_new (G_TYPE_DAEMON_FILE_MONITOR, NULL); daemon_monitor->remote_id = g_strdup (remote_id); daemon_monitor->remote_obj_path = g_strdup (remote_obj_path); _g_dbus_connection_get_for_async (daemon_monitor->remote_id, async_got_connection_cb, g_object_ref (daemon_monitor), NULL); return G_FILE_MONITOR (daemon_monitor); } The "events are now delivered immediately" thing with the new file monitoring changes means that we are much more likely to lose this race than we were before.... This needs to be fixed in gvfs and it will probably be a fairly substantial undertaking. Was this bug hit by real-world code or is it only something that you hit with your test program while trying to test the other bug?
Created attachment 312370 [details] fixed reproducer the testcase contained a bug: the source funcs didn't return false, so sometimes the program would get stuck in a tight loop, creating and trashing 1000s of files. this is a fixed version.
I don't think there is a huge problem just switching this to use _g_dbus_connection_get_sync(), we cache those, so if you did any kind of i/o to that mount you'll have it locally. However, it would be nice if we could avoid doing things sync for the proxy setup and the initial monitor call. In theory this is doable, as we could send the monitor.Subscribe() message and can then assume that requests from *us* will happen after the subscribe message by the ordering of the dbus messages. This means that if you start doing i/o after monitor was created you will see changes for any operations and the race is closed. Unfortunately it is really hard to do this correctly using GDbusProxy, as it always sends a GetNameOwner or StartServiceByName request during initialization, so it does not allow us to start the service by sending the initial Monitor request. Fortunately org.gtk.vfs.Monitor is pretty trivial, so we could do this without a proxy i guess.
Actually, at this point the remote is a unique id, so doing a sync init of the proxy doesn't actually do any i/o, so there might not be an issue.
Fixed here: https://git.gnome.org/browse/gvfs/commit/?id=7373acf9b15f40f1c01bd2a325b380ba9bc17d19
That commit seems to have created https://bugzilla.gnome.org/show_bug.cgi?id=756153