GNOME Bugzilla – Bug 708816
gvfs-daemon deadlock in peer_connection_closed
Last modified: 2013-09-26 11:34:34 UTC
gvfs-1.16.3-2.fc19.x86_64 libsoup-2.42.2-2.fc19.x86_64 gvfs-open with an http URL will hang for about 50 seconds as the gvfsd-http daemon fails to respond to requests. This is due to a deadlock when cancelling a task. Backtrace of gvfsd-http below.
+ Trace 232540
So, what happens is that a gvfs mount daemon gets a dbus-connection-died signal from one of the clients, and there was an outstanding operation. This then does in peer_connection_closed(): g_mutex_lock (&daemon->lock); for (l = daemon->jobs; l != NULL; l = l->next) { GVfsJob *job = G_VFS_JOB (l->data); if (G_VFS_IS_JOB_DBUS (job) && G_VFS_JOB_DBUS (job)->invocation && g_dbus_method_invocation_get_connection (G_VFS_JOB_DBUS (job)->invocation) == connection) g_vfs_job_cancel (job); } g_mutex_unlock (&daemon->lock); The g_vfs_job_cancel() emits a cancelled signal that eventually ends back in gvfsdaemon.c in job_finished_callback() to remove the job from the jobs list. However, this takes the daemon->lock again and deadlocks. Obvious fix is to cancel outside the lock. The question is whether that is threadsafe.
handle_cancel() does cancel outside the lock, so it better be safe :)
Created attachment 255821 [details] [review] GVfsDaemon: Don't deadlock on cliend disconnect There was a deadlock that could happen on client disconnect in peer_connection_closed(). If the cancelled job immediately called back into job_finished_callback() we would deadlock on daemon->mutex. So, make sure we cancel jobs without holding the lock, just like handle_cancel() does.
Attachment 255821 [details] pushed as 3448fa0 - GVfsDaemon: Don't deadlock on cliend disconnect