[gvfs/gnome-3-24] daemon: Prevent deadlock and invalid read when closing channels
- From: Ondrej Holy <oholy src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs/gnome-3-24] daemon: Prevent deadlock and invalid read when closing channels
- Date: Fri, 13 Apr 2018 08:32:02 +0000 (UTC)
commit 2712954cb6968f06b99aa2d22d490bad88d83ec1
Author: Ondrej Holy <oholy redhat com>
Date: Tue Apr 10 13:17:38 2018 +0200
daemon: Prevent deadlock and invalid read when closing channels
Commit e147e48 added missing mutex guards for job_sources, which may
unfortunately lead to deadlock because g_vfs_channel_force_close
synchronously calls g_vfs_job_source_closed which is also guarded by
the same mutex.
The deadlock reveals another bug which was in that code. The code
iterates over job_sources list, but g_vfs_job_source_closed removes
current element of the list, which leads to invalid reads and
potentially to segfaults also.
This patch tries to fix the both mentioned issues.
https://bugzilla.gnome.org/show_bug.cgi?id=794957
daemon/gvfsdaemon.c | 28 ++++++++++++++++++++++------
1 files changed, 22 insertions(+), 6 deletions(-)
---
diff --git a/daemon/gvfsdaemon.c b/daemon/gvfsdaemon.c
index 8305700..f13e4e4 100644
--- a/daemon/gvfsdaemon.c
+++ b/daemon/gvfsdaemon.c
@@ -1127,13 +1127,29 @@ g_vfs_daemon_close_active_channels (GVfsDaemon *daemon,
GVfsBackend *backend)
{
GList *l;
+ GVfsChannel *channel_to_close;
- g_mutex_lock (&daemon->lock);
+ do
+ {
+ channel_to_close = NULL;
- for (l = daemon->job_sources; l != NULL; l = l->next)
- if (G_VFS_IS_CHANNEL (l->data) &&
- g_vfs_channel_get_backend (G_VFS_CHANNEL (l->data)) == backend)
- g_vfs_channel_force_close (G_VFS_CHANNEL (l->data));
+ g_mutex_lock (&daemon->lock);
+ for (l = daemon->job_sources; l != NULL; l = l->next)
+ {
+ if (G_VFS_IS_CHANNEL (l->data) &&
+ g_vfs_channel_get_backend (G_VFS_CHANNEL (l->data)) == backend)
+ {
+ channel_to_close = g_object_ref (G_VFS_CHANNEL (l->data));
+ break;
+ }
+ }
+ g_mutex_unlock (&daemon->lock);
- g_mutex_unlock (&daemon->lock);
+ if (channel_to_close)
+ {
+ g_vfs_channel_force_close (channel_to_close);
+ g_object_unref (channel_to_close);
+ }
+ }
+ while (channel_to_close != NULL);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]