[gvfs/gdbus-core: 21/33] gdbus: Make cancellation work



commit 7637dd7cbb574d5b0e195a8905e837ab7b7fc0ba
Author: Tomas Bzatek <tbzatek redhat com>
Date:   Fri Jun 15 17:24:42 2012 +0200

    gdbus: Make cancellation work
    
    This mimics the old behaviour and works for sync and async.
    
    Requires new glib for g_dbus_connection_get_last_serial().

 client/gdaemonfile.c      |  194 ++++++++++++++++++++++++++++++++++++++++-----
 client/gdaemonmount.c     |    3 +
 client/gvfsdaemondbus.c   |  125 +++++++++++++++++++++++++++++
 client/gvfsdaemondbus.h   |    6 ++
 client/gvfsiconloadable.c |   13 +++-
 daemon/gvfsdaemon.c       |    1 -
 daemon/gvfsjobdbus.c      |   16 +++--
 daemon/gvfsjobdbus.h      |    2 +-
 8 files changed, 330 insertions(+), 30 deletions(-)
---
diff --git a/client/gdaemonfile.c b/client/gdaemonfile.c
index 093e044..14291b2 100644
--- a/client/gdaemonfile.c
+++ b/client/gdaemonfile.c
@@ -690,6 +690,7 @@ g_daemon_file_enumerate_children (GFile      *file,
   char *uri;
   GVfsDBusMount *proxy;
   gboolean res;
+  GError *local_error = NULL;
   
   g_print ("g_daemon_file_enumerate_children\n");
   
@@ -709,9 +710,16 @@ g_daemon_file_enumerate_children (GFile      *file,
                                              flags,
                                              uri,
                                              cancellable,
-                                             error);
+                                             &local_error);
   
   g_print ("g_daemon_file_enumerate_children: done, res = %d\n", res);
+
+  if (! res)
+    {
+      if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      g_propagate_error (error, local_error);
+    }
   
   g_free (path);
   g_free (uri);
@@ -808,6 +816,7 @@ g_daemon_file_query_info (GFile                *file,
   GVfsDBusMount *proxy;
   GVariant *iter_info;
   gboolean res;
+  GError *local_error = NULL;
 
   g_print ("g_daemon_file_query_info\n");
 
@@ -825,10 +834,17 @@ g_daemon_file_query_info (GFile                *file,
                                               uri,
                                               &iter_info,
                                               cancellable,
-                                              error);
+                                              &local_error);
 
   g_print ("g_daemon_file_query_info: done, res = %d\n", res);
 
+  if (! res)
+    {
+      if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      g_propagate_error (error, local_error);
+    }
+
   g_free (path);
   g_free (uri);
   g_object_unref (proxy);
@@ -853,6 +869,7 @@ typedef struct {
   int io_priority;
   GSimpleAsyncResult *result;
   GCancellable *cancellable;
+  gulong cancelled_tag;
 } AsyncCallQueryInfo;
 
 static void
@@ -906,6 +923,7 @@ query_info_async_cb (GVfsDBusMount *proxy,
   
 out:
   _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  _g_dbus_async_unsubscribe_cancellable (data->cancellable, data->cancelled_tag);
   data->result = NULL;
   g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
 }
@@ -937,6 +955,7 @@ query_info_async_get_proxy_cb (GVfsDBusMount *proxy,
                                    cancellable,
                                    (GAsyncReadyCallback) query_info_async_cb,
                                    data);
+  data->cancelled_tag = _g_dbus_async_subscribe_cancellable (connection, cancellable);
   
   g_free (uri);
 }
@@ -994,6 +1013,7 @@ typedef struct {
   GFileCreateFlags flags;
   GSimpleAsyncResult *result;
   GCancellable *cancellable;
+  gulong cancelled_tag;
 } AsyncCallFileReadWrite;
 
 static void
@@ -1048,6 +1068,7 @@ read_async_cb (GVfsDBusMount *proxy,
 
 out:
   _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  _g_dbus_async_unsubscribe_cancellable (data->cancellable, data->cancelled_tag);
   data->result = NULL;
   g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
 }
@@ -1078,6 +1099,7 @@ file_read_async_get_proxy_cb (GVfsDBusMount *proxy,
                                      cancellable,
                                      (GAsyncReadyCallback) read_async_cb,
                                      data);
+  data->cancelled_tag = _g_dbus_async_subscribe_cancellable (connection, cancellable);
 }
 
 static void
@@ -1132,6 +1154,7 @@ g_daemon_file_read (GFile *file,
   int fd;
   guint fd_id;
   guint32 pid;
+  GError *local_error = NULL;
 
   g_print ("g_daemon_file_read\n");
 
@@ -1149,10 +1172,17 @@ g_daemon_file_read (GFile *file,
                                                  &can_seek,
                                                  &fd_list,
                                                  cancellable,
-                                                 error);
+                                                 &local_error);
   
   g_print ("g_daemon_file_read: done, res = %d\n", res);
-  
+
+  if (! res)
+    {
+      if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      g_propagate_error (error, local_error);
+    }
+
   g_free (path);
   g_object_unref (proxy);
 
@@ -1190,6 +1220,7 @@ file_open_write (GFile *file,
   guint32 fd_id;
   guint32 pid;
   guint64 initial_offset;
+  GError *local_error = NULL;
 
   pid = get_pid_for_file (file);
 
@@ -1213,10 +1244,17 @@ file_open_write (GFile *file,
                                                   &initial_offset,
                                                   &fd_list,
                                                   cancellable,
-                                                  error);
+                                                  &local_error);
   
   g_print ("file_open_write: done, res = %d\n", res);
-  
+
+  if (! res)
+    {
+      if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      g_propagate_error (error, local_error);
+    }
+
   g_free (path);
   g_object_unref (proxy);
 
@@ -1277,6 +1315,7 @@ typedef struct {
   GCancellable *cancellable;
   guint32 flags;
   GMountOperation *mount_operation;
+  gulong cancelled_tag;
 } AsyncMountOp;
 
 static void
@@ -1383,6 +1422,7 @@ mount_mountable_async_cb (GVfsDBusMount *proxy,
 
 out:
   _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  _g_dbus_async_unsubscribe_cancellable (data->cancellable, data->cancelled_tag);
   g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
 }
 
@@ -1416,6 +1456,7 @@ mount_mountable_got_proxy_cb (GVfsDBusMount *proxy,
                                         cancellable,
                                         (GAsyncReadyCallback) mount_mountable_async_cb,
                                         data);
+  data->cancelled_tag = _g_dbus_async_subscribe_cancellable (connection, cancellable);
   
   g_object_unref (mount_source);
 }
@@ -1476,6 +1517,7 @@ start_mountable_async_cb (GVfsDBusMount *proxy,
     g_simple_async_result_take_error (orig_result, error);
 
   _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  _g_dbus_async_unsubscribe_cancellable (data->cancellable, data->cancelled_tag);
   data->result = NULL;
   g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
 }
@@ -1510,6 +1552,7 @@ start_mountable_got_proxy_cb (GVfsDBusMount *proxy,
                                         cancellable,
                                         (GAsyncReadyCallback) start_mountable_async_cb,
                                         data);
+  data->cancelled_tag = _g_dbus_async_subscribe_cancellable (connection, cancellable);
   
   g_object_unref (mount_source);
 }
@@ -1563,6 +1606,7 @@ stop_mountable_async_cb (GVfsDBusMount *proxy,
     g_simple_async_result_take_error (orig_result, error);
 
   _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  _g_dbus_async_unsubscribe_cancellable (data->cancellable, data->cancelled_tag);
   data->result = NULL;
   g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
 }
@@ -1598,6 +1642,7 @@ stop_mountable_got_proxy_cb (GVfsDBusMount *proxy,
                                        cancellable,
                                        (GAsyncReadyCallback) stop_mountable_async_cb,
                                        data);
+  data->cancelled_tag = _g_dbus_async_subscribe_cancellable (connection, cancellable);
 
   g_object_unref (mount_source);
 }
@@ -1651,6 +1696,7 @@ eject_mountable_async_cb (GVfsDBusMount *proxy,
     g_simple_async_result_take_error (orig_result, error);
 
   _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  _g_dbus_async_unsubscribe_cancellable (data->cancellable, data->cancelled_tag);
   data->result = NULL;
   g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
 }
@@ -1686,6 +1732,7 @@ eject_mountable_got_proxy_cb (GVfsDBusMount *proxy,
                                         cancellable,
                                         (GAsyncReadyCallback) eject_mountable_async_cb,
                                         data);
+  data->cancelled_tag = _g_dbus_async_subscribe_cancellable (connection, cancellable);
 
   g_object_unref (mount_source);
 }
@@ -1757,6 +1804,7 @@ unmount_mountable_async_cb (GVfsDBusMount *proxy,
     g_simple_async_result_take_error (orig_result, error);
 
   _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  _g_dbus_async_unsubscribe_cancellable (data->cancellable, data->cancelled_tag);
   data->result = NULL;
   g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
 }
@@ -1792,6 +1840,7 @@ unmount_mountable_got_proxy_cb (GVfsDBusMount *proxy,
                                           cancellable,
                                           (GAsyncReadyCallback) unmount_mountable_async_cb,
                                           data);
+  data->cancelled_tag = _g_dbus_async_subscribe_cancellable (connection, cancellable);
 
   g_object_unref (mount_source);
 }
@@ -1845,6 +1894,7 @@ poll_mountable_async_cb (GVfsDBusMount *proxy,
     g_simple_async_result_take_error (orig_result, error);
 
   _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  _g_dbus_async_unsubscribe_cancellable (data->cancellable, data->cancelled_tag);
   data->result = NULL;
   g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
 }
@@ -1870,6 +1920,7 @@ poll_mountable_got_proxy_cb (GVfsDBusMount *proxy,
                                        cancellable,
                                        (GAsyncReadyCallback) poll_mountable_async_cb,
                                        data);
+  data->cancelled_tag = _g_dbus_async_subscribe_cancellable (connection, cancellable);
 }
 
 static void
@@ -2074,6 +2125,7 @@ g_daemon_file_query_filesystem_info (GFile                *file,
   char *path;
   gboolean res;
   GVariant *iter_info;
+  GError *local_error = NULL;
 
   g_print ("g_daemon_file_query_filesystem_info\n");
 
@@ -2087,10 +2139,17 @@ g_daemon_file_query_filesystem_info (GFile                *file,
                                                          attributes ? attributes : "",
                                                          &iter_info,
                                                          cancellable,
-                                                         error);
+                                                         &local_error);
   
   g_print ("g_daemon_file_query_filesystem_info: done, res = %d\n", res);
 
+  if (! res)
+    {
+      if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      g_propagate_error (error, local_error);
+    }
+
   g_free (path);
   g_object_unref (proxy);
 
@@ -2111,6 +2170,7 @@ typedef struct {
   int io_priority;
   GSimpleAsyncResult *result;
   GCancellable *cancellable;
+  gulong cancelled_tag;
 } AsyncCallQueryFsInfo;
 
 static void
@@ -2159,6 +2219,7 @@ query_fs_info_async_cb (GVfsDBusMount *proxy,
   
 out:
   _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  _g_dbus_async_unsubscribe_cancellable (data->cancellable, data->cancelled_tag);
   data->result = NULL;
   g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
 }
@@ -2188,6 +2249,7 @@ query_info_fs_async_get_proxy_cb (GVfsDBusMount *proxy,
                                               cancellable,
                                               (GAsyncReadyCallback) query_fs_info_async_cb,
                                               data);
+  data->cancelled_tag = _g_dbus_async_subscribe_cancellable (connection, cancellable);
   
   g_free (uri);
 }
@@ -2323,6 +2385,7 @@ g_daemon_file_set_display_name (GFile *file,
   GVfsDBusMount *proxy;
   char *path;
   gboolean res;
+  GError *local_error = NULL;
 
   daemon_file = G_DAEMON_FILE (file);
   mount_info = NULL;
@@ -2337,9 +2400,16 @@ g_daemon_file_set_display_name (GFile *file,
                                                     display_name ? display_name : "",
                                                     &new_path,
                                                     cancellable,
-                                                    error);
+                                                    &local_error);
   g_print ("g_daemon_file_set_display_name: done, res = %d\n", res);
 
+  if (! res)
+    {
+      if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      g_propagate_error (error, local_error);
+    }
+
   g_free (path);
   g_object_unref (proxy);
 
@@ -2363,6 +2433,7 @@ g_daemon_file_delete (GFile *file,
   GVfsDBusMount *proxy;
   char *path;
   gboolean res;
+  GError *local_error = NULL;
 
   g_print ("g_daemon_file_delete\n");
 
@@ -2373,9 +2444,16 @@ g_daemon_file_delete (GFile *file,
   res = gvfs_dbus_mount_call_delete_sync (proxy,
                                           path,
                                           cancellable,
-                                          error);
+                                          &local_error);
   g_print ("g_daemon_file_delete: done, res = %d\n", res);
 
+  if (! res)
+    {
+      if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      g_propagate_error (error, local_error);
+    }
+
   g_free (path);
   g_object_unref (proxy);
   
@@ -2390,6 +2468,7 @@ g_daemon_file_trash (GFile *file,
   GVfsDBusMount *proxy;
   char *path;
   gboolean res;
+  GError *local_error = NULL;
 
   g_print ("g_daemon_file_trash\n");
 
@@ -2400,9 +2479,16 @@ g_daemon_file_trash (GFile *file,
   res = gvfs_dbus_mount_call_trash_sync (proxy,
                                          path,
                                          cancellable,
-                                         error);
+                                         &local_error);
   g_print ("g_daemon_file_trash: done, res = %d\n", res);
 
+  if (! res)
+    {
+      if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      g_propagate_error (error, local_error);
+    }
+
   g_free (path);
   g_object_unref (proxy);
   
@@ -2417,6 +2503,7 @@ g_daemon_file_make_directory (GFile *file,
   GVfsDBusMount *proxy;
   char *path;
   gboolean res;
+  GError *local_error = NULL;
 
   g_print ("g_daemon_file_make_directory\n");
 
@@ -2427,9 +2514,16 @@ g_daemon_file_make_directory (GFile *file,
   res = gvfs_dbus_mount_call_make_directory_sync (proxy,
                                                   path,
                                                   cancellable,
-                                                  error);
+                                                  &local_error);
   g_print ("g_daemon_file_make_directory: done, res = %d\n", res);
 
+  if (! res)
+    {
+      if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      g_propagate_error (error, local_error);
+    }
+
   g_free (path);
   g_object_unref (proxy);
   
@@ -2445,6 +2539,7 @@ g_daemon_file_make_symbolic_link (GFile *file,
   GVfsDBusMount *proxy;
   char *path;
   gboolean res;
+  GError *local_error = NULL;
 
   g_print ("g_daemon_file_make_symbolic_link\n");
 
@@ -2456,9 +2551,16 @@ g_daemon_file_make_symbolic_link (GFile *file,
                                                       path,
                                                       symlink_value ? symlink_value : "",
                                                       cancellable,
-                                                      error);
+                                                      &local_error);
   g_print ("g_daemon_file_make_symbolic_link: done, res = %d\n", res);
 
+  if (! res)
+    {
+      if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      g_propagate_error (error, local_error);
+    }
+
   g_free (path);
   g_object_unref (proxy);
   
@@ -2475,6 +2577,7 @@ g_daemon_file_query_settable_attributes (GFile                      *file,
   gboolean res;
   GVariant *iter_list;
   GFileAttributeInfoList *list;
+  GError *local_error = NULL;
 
   g_print ("g_daemon_file_query_settable_attributes\n");
 
@@ -2487,9 +2590,16 @@ g_daemon_file_query_settable_attributes (GFile                      *file,
                                                              path,
                                                              &iter_list,
                                                              cancellable,
-                                                             error);
+                                                             &local_error);
   g_print ("g_daemon_file_query_settable_attributes: done, res = %d\n", res);
 
+  if (! res)
+    {
+      if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      g_propagate_error (error, local_error);
+    }
+
   g_free (path);
   g_object_unref (proxy);
 
@@ -2512,6 +2622,7 @@ g_daemon_file_query_writable_namespaces (GFile                      *file,
   gboolean res;
   GVariant *iter_list;
   GFileAttributeInfoList *list;
+  GError *local_error = NULL;
 
   g_print ("g_daemon_file_query_writable_namespaces\n");
 
@@ -2524,9 +2635,16 @@ g_daemon_file_query_writable_namespaces (GFile                      *file,
                                                              path,
                                                              &iter_list,
                                                              cancellable,
-                                                             error);
+                                                             &local_error);
   g_print ("g_daemon_file_query_writable_namespaces: done, res = %d\n", res);
 
+  if (! res)
+    {
+      if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      g_propagate_error (error, local_error);
+    }
+
   g_free (path);
   g_object_unref (proxy);
 
@@ -2648,19 +2766,24 @@ g_daemon_file_set_attribute (GFile *file,
   g_print ("g_daemon_file_set_attribute: done, res = %d\n", res);
 
   g_free (path);
-  g_object_unref (proxy);
 
   if (! res)
     {
+      if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      else
       if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY))
 	{
 	  g_error_free (my_error);
+	  g_object_unref (proxy);
 	  goto retry;
 	}
       g_propagate_error (error, my_error);
       return FALSE;
     }
 
+  g_object_unref (proxy);
+
   return TRUE;
 }
 
@@ -2844,19 +2967,24 @@ retry:
       g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (progress_skeleton));
       g_object_unref (progress_skeleton);
     }
-  if (proxy)
-    g_object_unref (proxy);
 
   if (! res)
     {
+      if (proxy && g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      else
       if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY))
         {
           g_error_free (my_error);
+          g_object_unref (proxy);
           goto retry;
         }
       g_propagate_error (error, my_error);
     }
 
+  if (proxy)
+    g_object_unref (proxy);
+
   g_free (local_path);
   g_free (obj_path);
 
@@ -2921,6 +3049,7 @@ g_daemon_file_monitor_dir (GFile* file,
   char *path;
   char *obj_path;
   gboolean res;
+  GError *local_error = NULL;
 
   g_print ("g_daemon_file_monitor_dir\n");
 
@@ -2938,9 +3067,16 @@ g_daemon_file_monitor_dir (GFile* file,
                                                             flags,
                                                             &obj_path,
                                                             cancellable,
-                                                            error);
+                                                            &local_error);
   g_print ("g_daemon_file_monitor_dir: done, res = %d\n", res);
-  
+
+  if (! res)
+    {
+      if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      g_propagate_error (error, local_error);
+    }
+
   g_free (path);
   g_object_unref (proxy);
 
@@ -2969,6 +3105,7 @@ g_daemon_file_monitor_file (GFile* file,
   char *path;
   char *obj_path;
   gboolean res;
+  GError *local_error = NULL;
 
   g_print ("g_daemon_file_monitor_file\n");
 
@@ -2986,9 +3123,16 @@ g_daemon_file_monitor_file (GFile* file,
                                                        flags,
                                                        &obj_path,
                                                        cancellable,
-                                                       error);
+                                                       &local_error);
   g_print ("g_daemon_file_monitor_file: done, res = %d\n", res);
-  
+
+  if (! res)
+    {
+      if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      g_propagate_error (error, local_error);
+    }
+
   g_free (path);
   g_object_unref (proxy);
 
@@ -3046,6 +3190,7 @@ file_open_write_async_cb (GVfsDBusMount *proxy,
 
 out:
   _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  _g_dbus_async_unsubscribe_cancellable (data->cancellable, data->cancelled_tag);
   data->result = NULL;
   g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
 }
@@ -3080,6 +3225,7 @@ file_open_write_async_get_proxy_cb (GVfsDBusMount *proxy,
                                        cancellable,
                                        (GAsyncReadyCallback) file_open_write_async_cb,
                                        data);
+  data->cancelled_tag = _g_dbus_async_subscribe_cancellable (connection, cancellable);
 }
 
 static void
@@ -3182,6 +3328,7 @@ typedef struct {
   GSimpleAsyncResult *result;
   GCancellable *cancellable;
   GDaemonFileEnumerator *enumerator;
+  gulong cancelled_tag;
 } AsyncCallEnumerate;
 
 static void
@@ -3225,6 +3372,7 @@ enumerate_children_async_cb (GVfsDBusMount *proxy,
 
 out:
   _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  _g_dbus_async_unsubscribe_cancellable (data->cancellable, data->cancelled_tag);
   data->result = NULL;
   g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
 }
@@ -3259,6 +3407,7 @@ enumerate_children_async_get_proxy_cb (GVfsDBusMount *proxy,
                                   cancellable,
                                   (GAsyncReadyCallback) enumerate_children_async_cb,
                                   data);
+  data->cancelled_tag = _g_dbus_async_subscribe_cancellable (connection, cancellable);
   
   g_free (uri);
   g_free (obj_path);
@@ -3454,6 +3603,7 @@ typedef struct {
   GMountInfo *mount_info;
   GSimpleAsyncResult *result;
   GCancellable *cancellable;
+  gulong cancelled_tag;
 } AsyncCallSetDisplayName;
 
 static void
@@ -3500,6 +3650,7 @@ set_display_name_async_cb (GVfsDBusMount *proxy,
 
   out:
     _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+    _g_dbus_async_unsubscribe_cancellable (data->cancellable, data->cancelled_tag);
     data->result = NULL;
     g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
 }
@@ -3527,6 +3678,7 @@ set_display_name_async_get_proxy_cb (GVfsDBusMount *proxy,
                                          cancellable,
                                          (GAsyncReadyCallback) set_display_name_async_cb,
                                          data);
+  data->cancelled_tag = _g_dbus_async_subscribe_cancellable (connection, cancellable);
 }
 
 static void
diff --git a/client/gdaemonmount.c b/client/gdaemonmount.c
index 125413f..8f2df11 100644
--- a/client/gdaemonmount.c
+++ b/client/gdaemonmount.c
@@ -182,6 +182,7 @@ typedef struct {
   GMountUnmountFlags flags;
   GDBusConnection *connection;
   GVfsDBusMount *proxy;
+  gulong cancelled_tag;
 } AsyncProxyCreate;
 
 static void
@@ -218,6 +219,7 @@ unmount_reply (GVfsDBusMount *proxy,
     }
   
   _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable);
+  _g_dbus_async_unsubscribe_cancellable (data->cancellable, data->cancelled_tag);
   async_proxy_create_free (data);
 }
 
@@ -253,6 +255,7 @@ async_proxy_new_cb (GObject *source_object,
                                 data->cancellable,
                                 (GAsyncReadyCallback) unmount_reply,
                                 data);
+  data->cancelled_tag = _g_dbus_async_subscribe_cancellable (data->connection, data->cancellable);
   
   g_object_unref (mount_source);
 }
diff --git a/client/gvfsdaemondbus.c b/client/gvfsdaemondbus.c
index 0138349..4feb0ea 100644
--- a/client/gvfsdaemondbus.c
+++ b/client/gvfsdaemondbus.c
@@ -492,6 +492,131 @@ _g_dbus_connection_get_for_async (const char *dbus_id,
     }
 }
 
+
+typedef struct {
+  GDBusConnection *connection;
+  guint32 serial;
+} AsyncCallCancelData;
+
+static void
+async_call_cancel_data_free (gpointer _data)
+{
+  AsyncCallCancelData *data = _data;
+
+  g_object_unref (data->connection);
+  g_free (data);
+}
+
+static void
+cancelled_got_proxy (GObject *source_object,
+                     GAsyncResult *res,
+                     gpointer user_data)
+{
+  guint32 serial = GPOINTER_TO_UINT (user_data);
+  GVfsDBusDaemon *proxy;
+  GError *error = NULL;
+
+  proxy = gvfs_dbus_daemon_proxy_new_finish (res, &error);
+  if (! proxy)
+    {
+      g_printerr ("Failed to construct daemon proxy for cancellation: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+      return;
+    }
+
+  gvfs_dbus_daemon_call_cancel (proxy,
+                                serial,
+                                NULL,
+                                NULL,  /* we don't need any reply */
+                                NULL);
+  g_object_unref (proxy);
+}
+
+/* Might be called on another thread */
+static void
+async_call_cancelled_cb (GCancellable *cancellable,
+                         gpointer _data)
+{
+  AsyncCallCancelData *data = _data;
+
+  /* TODO: use shared daemon proxy on private connection if possible */
+  gvfs_dbus_daemon_proxy_new (data->connection,
+                              G_BUS_NAME_OWNER_FLAGS_NONE,
+                              NULL,
+                              G_VFS_DBUS_DAEMON_PATH,
+                              NULL,
+                              cancelled_got_proxy,
+                              GUINT_TO_POINTER (data->serial));  /* not passing "data" in as long it may not exist anymore between async calls */
+}
+
+gulong
+_g_dbus_async_subscribe_cancellable (GDBusConnection *connection, GCancellable *cancellable)
+{
+  AsyncCallCancelData *cancel_data;
+  gulong cancelled_tag = 0;
+
+  if (cancellable)
+    {
+      cancel_data = g_new0 (AsyncCallCancelData, 1);
+      cancel_data->connection = g_object_ref (connection);
+      /* make sure we get the serial *after* the message has been sent, otherwise
+       * it will be 0
+       */
+      cancel_data->serial = g_dbus_connection_get_last_serial (connection);
+      cancelled_tag =
+        g_signal_connect_data (cancellable, "cancelled",
+                               (GCallback)async_call_cancelled_cb,
+                               cancel_data,
+                               (GClosureNotify)async_call_cancel_data_free,
+                               0);
+    }
+
+  return cancelled_tag;
+}
+
+void
+_g_dbus_async_unsubscribe_cancellable (GCancellable *cancellable, gulong cancelled_tag)
+{
+  if (cancelled_tag)
+    {
+      g_assert (cancellable != NULL);
+      g_signal_handler_disconnect (cancellable, cancelled_tag);
+    }
+}
+
+void
+ _g_dbus_send_cancelled_sync (GDBusConnection *connection)
+{
+  guint32 serial;
+  GVfsDBusDaemon *proxy;
+  GError *error = NULL;
+
+  serial = g_dbus_connection_get_last_serial (connection);
+
+  proxy = gvfs_dbus_daemon_proxy_new_sync (connection,
+                                           G_BUS_NAME_OWNER_FLAGS_NONE,
+                                           NULL,
+                                           G_VFS_DBUS_DAEMON_PATH,
+                                           NULL,
+                                           &error);
+  if (! proxy)
+    {
+      g_printerr ("Failed to construct daemon proxy for cancellation: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+      return;
+    }
+
+  gvfs_dbus_daemon_call_cancel (proxy,
+                                serial,
+                                NULL,
+                                NULL,  /* we don't need any reply */
+                                NULL);
+  g_object_unref (proxy);
+}
+
+
 /*************************************************************************
  *               get per-thread synchronous dbus connections             *
  *************************************************************************/
diff --git a/client/gvfsdaemondbus.h b/client/gvfsdaemondbus.h
index 6f453b3..3128c9e 100644
--- a/client/gvfsdaemondbus.h
+++ b/client/gvfsdaemondbus.h
@@ -64,6 +64,12 @@ void        _g_simple_async_result_complete_with_cancellable
                                                         (GSimpleAsyncResult             *result,
                                                          GCancellable                   *cancellable);
 
+gulong          _g_dbus_async_subscribe_cancellable     (GDBusConnection                *connection,
+                                                         GCancellable                   *cancellable);
+void            _g_dbus_async_unsubscribe_cancellable   (GCancellable                   *cancellable,
+                                                         gulong                          cancelled_tag);
+void            _g_dbus_send_cancelled_sync             (GDBusConnection                *connection);
+
 G_END_DECLS
 
 #endif /* __G_VFS_DAEMON_DBUS_H__ */
diff --git a/client/gvfsiconloadable.c b/client/gvfsiconloadable.c
index 77dcd17..4c43510 100644
--- a/client/gvfsiconloadable.c
+++ b/client/gvfsiconloadable.c
@@ -92,6 +92,7 @@ g_vfs_icon_load (GLoadableIcon  *icon,
   GUnixFDList *fd_list;
   int fd;
   guint32 fd_id;
+  GError *local_error = NULL;
 
   g_print ("gvfsiconloadable.c: g_vfs_icon_load\n");
 
@@ -106,10 +107,17 @@ g_vfs_icon_load (GLoadableIcon  *icon,
                                                       &can_seek,
                                                       &fd_list,
                                                       cancellable,
-                                                      error);
+                                                      &local_error);
   
   g_print ("gvfsiconloadable.c: g_vfs_icon_load: done, res = %d\n", res);
   
+  if (! res)
+    {
+      if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)));
+      g_propagate_error (error, local_error);
+    }
+
   g_object_unref (proxy);
 
   if (! res)
@@ -143,6 +151,7 @@ typedef struct {
   GCancellable *cancellable;
   CreateProxyAsyncCallback callback;
   gpointer callback_data;
+  gulong cancelled_tag;
 } AsyncPathCall;
 
 
@@ -308,6 +317,7 @@ open_icon_read_cb (GVfsDBusMount *proxy,
 
 out:
   _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable);
+  _g_dbus_async_unsubscribe_cancellable (data->cancellable, data->cancelled_tag);
   async_path_call_free (data);
 }
 
@@ -327,6 +337,7 @@ load_async_cb (GVfsDBusMount *proxy,
                                            cancellable,
                                            (GAsyncReadyCallback) open_icon_read_cb,
                                            callback_data);
+  data->cancelled_tag = _g_dbus_async_subscribe_cancellable (data->connection, cancellable);
 }
 
 static void
diff --git a/daemon/gvfsdaemon.c b/daemon/gvfsdaemon.c
index 16e89f3..5cbf7dd 100644
--- a/daemon/gvfsdaemon.c
+++ b/daemon/gvfsdaemon.c
@@ -254,7 +254,6 @@ g_vfs_daemon_init (GVfsDaemon *daemon)
 
   daemon->daemon_skeleton = gvfs_dbus_daemon_skeleton_new ();
   g_signal_connect (daemon->daemon_skeleton, "handle-get-connection", G_CALLBACK (handle_get_connection), daemon);
-  /* TODO: this might never be called on this side */
   g_signal_connect (daemon->daemon_skeleton, "handle-cancel", G_CALLBACK (handle_cancel), daemon);
   
   error = NULL;
diff --git a/daemon/gvfsjobdbus.c b/daemon/gvfsjobdbus.c
index 63d4436..51bcfe5 100644
--- a/daemon/gvfsjobdbus.c
+++ b/daemon/gvfsjobdbus.c
@@ -168,12 +168,16 @@ send_reply (GVfsJob *job)
 gboolean
 g_vfs_job_dbus_is_serial (GVfsJobDBus *job_dbus,
                           GDBusConnection *connection,
-			  guint serial)
+			  guint32 serial)
 {
-  return TRUE;
+  GDBusMessage *message;
+  GDBusConnection *message_connection;
   
-  /* FIXME 
-  return job_dbus->connection == connection &&
-    dbus_message_get_serial (job_dbus->message) == serial;
-    */
+  message = g_dbus_method_invocation_get_message (job_dbus->invocation);
+  message_connection = g_dbus_method_invocation_get_connection (job_dbus->invocation);
+  
+  g_print ("g_vfs_job_dbus_is_serial: serial = %u, message serial = %u, connection = %p, message connection = %p\n", serial, g_dbus_message_get_serial (message), connection, message_connection);
+  
+  return message_connection == connection &&
+      g_dbus_message_get_serial (message) == serial;
 }
diff --git a/daemon/gvfsjobdbus.h b/daemon/gvfsjobdbus.h
index ffbb510..85f5771 100644
--- a/daemon/gvfsjobdbus.h
+++ b/daemon/gvfsjobdbus.h
@@ -60,7 +60,7 @@ GType g_vfs_job_dbus_get_type (void) G_GNUC_CONST;
 
 gboolean g_vfs_job_dbus_is_serial (GVfsJobDBus     *job_dbus,
                                    GDBusConnection *connection,
-                                   guint            serial);
+                                   guint32          serial);
 
 G_END_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]