[gvfs] backend: Fix crashes when "Volume is busy" prompt is shown
- From: Ondrej Holy <oholy src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs] backend: Fix crashes when "Volume is busy" prompt is shown
- Date: Thu, 15 Mar 2018 16:33:11 +0000 (UTC)
commit 7c27d2b78f27455ee33012e6cbf49af9a98a20e6
Author: Ondrej Holy <oholy redhat com>
Date: Thu Mar 15 11:26:29 2018 +0100
backend: Fix crashes when "Volume is busy" prompt is shown
Backend crashes in on_show_processes_reply callback if
g_vfs_backend_unmount_with_operation async call has been completed
over on_update_processes_timeout in the meantime and releases GTask
data (i.e. "Volume is busy" prompt is being shown and blocking
operations have been finished).
This patch simplify the handling. With this patch, the async call
is completed only from one place, on_show_processes_reply. If there
are no more processes, g_mount_source_abort is called from
on_update_processes_timeout only and the reply is handled by
on_show_processes_reply consequently. This prevents the crashes.
Just a note that client side ensures that on_show_processes_reply is
called only once.
https://bugzilla.gnome.org/show_bug.cgi?id=794113
daemon/gvfsbackend.c | 53 +++++++++++++++++---------------------------------
1 files changed, 18 insertions(+), 35 deletions(-)
---
diff --git a/daemon/gvfsbackend.c b/daemon/gvfsbackend.c
index b909603..a622f6e 100644
--- a/daemon/gvfsbackend.c
+++ b/daemon/gvfsbackend.c
@@ -832,32 +832,35 @@ typedef struct
{
GMountSource *mount_source;
- gboolean ret;
- gboolean aborted;
- gint choice;
-
const gchar *message;
const gchar *choices[3];
- gboolean completed;
+ gboolean no_more_processes;
guint timeout_id;
} UnmountWithOpData;
static void
-complete_unmount_with_op (GTask *task, gboolean no_more_processes)
+on_show_processes_reply (GMountSource *mount_source,
+ GAsyncResult *res,
+ gpointer user_data)
{
+ GTask *task = G_TASK (user_data);
UnmountWithOpData *data = g_task_get_task_data (task);
+ gboolean ret, aborted;
+ gint choice;
- g_source_remove (data->timeout_id);
+ if (data->timeout_id != 0)
+ g_source_remove (data->timeout_id);
- if (!no_more_processes && !data->ret)
+ ret = g_mount_source_show_processes_finish (mount_source, res, &aborted, &choice);
+ if (!data->no_more_processes && !ret)
{
/* If the "show-processes" signal wasn't handled */
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_BUSY,
_("File system is busy"));
}
- else if (!no_more_processes && (data->aborted || data->choice == 1))
+ else if (!data->no_more_processes && (aborted || choice == 1))
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED_HANDLED,
"GMountOperation aborted");
@@ -867,30 +870,9 @@ complete_unmount_with_op (GTask *task, gboolean no_more_processes)
g_task_return_boolean (task, TRUE);
}
- data->completed = TRUE;
g_object_unref (task);
}
-static void
-on_show_processes_reply (GMountSource *mount_source,
- GAsyncResult *res,
- gpointer user_data)
-{
- GTask *task = G_TASK (user_data);
- UnmountWithOpData *data = g_task_get_task_data (task);
-
- /* Do nothing if we've handled this already */
- if (data->completed)
- return;
-
- data->ret = g_mount_source_show_processes_finish (mount_source,
- res,
- &data->aborted,
- &data->choice);
-
- complete_unmount_with_op (task, FALSE);
-}
-
static gboolean
on_update_processes_timeout (gpointer user_data)
{
@@ -902,9 +884,11 @@ on_update_processes_timeout (gpointer user_data)
if (!g_vfs_daemon_has_blocking_processes (daemon))
{
- /* no more processes, abort mount op */
g_mount_source_abort (data->mount_source);
- complete_unmount_with_op (task, TRUE);
+ data->timeout_id = 0;
+ data->no_more_processes = TRUE;
+
+ return G_SOURCE_REMOVE;
}
else
{
@@ -916,10 +900,9 @@ on_update_processes_timeout (gpointer user_data)
(GAsyncReadyCallback) on_show_processes_reply,
task);
g_array_unref (processes);
- }
- /* keep timeout around */
- return TRUE;
+ return G_SOURCE_CONTINUE;
+ }
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]