[gvfs] Attach cancellable to async result and check in finish functions
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs] Attach cancellable to async result and check in finish functions
- Date: Fri, 2 Apr 2010 14:54:16 +0000 (UTC)
commit d80c63deb48e07b328ced31b38af878314d40040
Author: Benjamin Otte <otte redhat com>
Date: Wed Mar 31 15:58:37 2010 +0200
Attach cancellable to async result and check in finish functions
This makes sure we always return ERROR_CANCELLED, just like we want to
guarantee and avoids crashes in the file chooser.
There should be API in GSimpleAsyncResult to attach a GCancellable that
does this job for us, but so far there isn't, so we use
g_object_get/set_data() and check the cancellables manually in the
finish function.
https://bugzilla.gnome.org/show_bug.cgi?id=614099
client/gdaemonfileenumerator.c | 57 +++++++++++++++++++++++++++++++++++-----
1 files changed, 50 insertions(+), 7 deletions(-)
---
diff --git a/client/gdaemonfileenumerator.c b/client/gdaemonfileenumerator.c
index be27545..46df64a 100644
--- a/client/gdaemonfileenumerator.c
+++ b/client/gdaemonfileenumerator.c
@@ -53,7 +53,6 @@ struct _GDaemonFileEnumerator
/* For async ops, also protected by infos lock */
int async_requested_files;
- GCancellable *async_cancel;
gulong cancelled_tag;
guint timeout_tag;
GSimpleAsyncResult *async_res;
@@ -220,6 +219,24 @@ add_metadata (GFileInfo *info,
g_free (path);
}
+static GCancellable *
+simple_async_result_get_cancellable (GSimpleAsyncResult *res)
+{
+ return g_object_get_data (G_OBJECT (res), "file-enumerator-cancellable");
+}
+
+static void
+simple_async_result_set_cancellable (GSimpleAsyncResult *res,
+ GCancellable *cancellable)
+{
+ if (!cancellable)
+ return;
+
+ g_object_set_data_full (G_OBJECT (res),
+ "file-enumerator-cancellable",
+ g_object_ref (cancellable),
+ g_object_unref);
+}
/* Called with infos lock held */
static void
@@ -229,6 +246,8 @@ trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok)
if (daemon->cancelled_tag != 0)
{
+ GCancellable *cancellable = simple_async_result_get_cancellable (daemon->async_res);
+
/* If ok, we're a normal callback on the main thread,
ensure protection against a thread cancelling and
running the callback again.
@@ -240,10 +259,10 @@ trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok)
handler.
*/
if (ok)
- g_cancellable_disconnect (daemon->async_cancel,
+ g_cancellable_disconnect (cancellable,
daemon->cancelled_tag);
else
- g_signal_handler_disconnect (daemon->async_cancel,
+ g_signal_handler_disconnect (cancellable,
daemon->cancelled_tag);
}
@@ -278,7 +297,6 @@ trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok)
g_simple_async_result_complete_in_idle (daemon->async_res);
- daemon->async_cancel = 0;
daemon->cancelled_tag = 0;
if (daemon->timeout_tag != 0)
@@ -489,12 +507,12 @@ g_daemon_file_enumerator_next_files_async (GFileEnumerator *enumerator,
}
G_LOCK (infos);
- daemon->async_cancel = cancellable;
daemon->cancelled_tag = 0;
daemon->timeout_tag = 0;
daemon->async_requested_files = num_files;
daemon->async_res = g_simple_async_result_new (G_OBJECT (enumerator), callback, user_data,
g_daemon_file_enumerator_next_files_async);
+ simple_async_result_set_cancellable (daemon->async_res, cancellable);
/* Maybe we already have enough info to fulfill the requeust already */
if (daemon->done ||
@@ -515,12 +533,24 @@ g_daemon_file_enumerator_next_files_async (GFileEnumerator *enumerator,
static GList *
g_daemon_file_enumerator_next_files_finish (GFileEnumerator *enumerator,
- GAsyncResult *result,
+ GAsyncResult *res,
GError **error)
{
+ GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (res);
+ GCancellable *cancellable;
GList *l;
- l = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+ cancellable = simple_async_result_get_cancellable (result);
+ if (g_cancellable_is_cancelled (cancellable))
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ "%s", _("Operation was cancelled"));
+ return NULL;
+ }
+
+ l = g_simple_async_result_get_op_res_gpointer (result);
g_list_foreach (l, (GFunc)g_object_ref, NULL);
return g_list_copy (l);
}
@@ -549,6 +579,7 @@ g_daemon_file_enumerator_close_async (GFileEnumerator *enumerator,
res = g_simple_async_result_new (G_OBJECT (enumerator), callback, user_data,
g_daemon_file_enumerator_close_async);
+ simple_async_result_set_cancellable (res, cancellable);
g_simple_async_result_complete_in_idle (res);
g_object_unref (res);
}
@@ -558,5 +589,17 @@ g_daemon_file_enumerator_close_finish (GFileEnumerator *enumerator,
GAsyncResult *result,
GError **error)
{
+ GCancellable *cancellable;
+
+ cancellable = simple_async_result_get_cancellable (G_SIMPLE_ASYNC_RESULT (result));
+ if (g_cancellable_is_cancelled (cancellable))
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ "%s", _("Operation was cancelled"));
+ return FALSE;
+ }
+
return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]