[gvfs] Use new race-free cancellable signal connect APIs (#572844)



commit 5bebce4592fee584bbc6db29a3e62b4005a1a71f
Author: Alexander Larsson <alexl redhat com>
Date:   Fri May 15 10:47:49 2009 +0200

    Use new race-free cancellable signal connect APIs (#572844)
---
 client/gdaemonfileenumerator.c |   23 ++++++++++++++++++-----
 common/gdbusutils.c            |    9 ++++-----
 daemon/gvfsbackendftp.c        |   16 +++++++++-------
 3 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/client/gdaemonfileenumerator.c b/client/gdaemonfileenumerator.c
index 1aec092..b650eaf 100644
--- a/client/gdaemonfileenumerator.c
+++ b/client/gdaemonfileenumerator.c
@@ -162,6 +162,20 @@ trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok)
 {
   GList *rest, *l;
 
+  if (daemon->cancelled_tag != 0)
+    g_cancellable_disconnect (daemon->async_cancel,
+			      daemon->cancelled_tag);
+
+  /* cancelled signal handler won't execute after this */
+
+  /* TODO: There is actually a small race here, where
+     trigger_async_done could happen twice if the operation
+     succeeds for some other reason and cancellation happens
+     on some other thread right before the above call.
+     However, this can only happen if cancellation happens
+     outside the main thread which is kinda unusual for async
+     ops. However, it would be nice to handle this too. */
+
   if (ok)
     {
       l = daemon->infos;
@@ -181,9 +195,6 @@ trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok)
 
   g_simple_async_result_complete_in_idle (daemon->async_res);
   
-  if (daemon->cancelled_tag != 0)
-    g_signal_handler_disconnect (daemon->async_cancel,
-				 daemon->cancelled_tag);
   daemon->async_cancel = 0;
   daemon->cancelled_tag = 0;
 
@@ -400,10 +411,12 @@ g_daemon_file_enumerator_next_files_async (GFileEnumerator     *enumerator,
     trigger_async_done (daemon, TRUE);
   else
     {
-      if (cancellable)
-	daemon->cancelled_tag = g_signal_connect (cancellable, "cancelled", (GCallback)async_cancelled, daemon);
       daemon->timeout_tag = g_timeout_add (G_VFS_DBUS_TIMEOUT_MSECS,
 					   async_timeout, daemon);
+      if (cancellable)
+	daemon->cancelled_tag =
+	  g_cancellable_connect (cancellable, (GCallback)async_cancelled,
+				 daemon, NULL);
     }
   
   G_UNLOCK (infos);
diff --git a/common/gdbusutils.c b/common/gdbusutils.c
index c3f3f33..f9d1889 100644
--- a/common/gdbusutils.c
+++ b/common/gdbusutils.c
@@ -679,8 +679,8 @@ fd_source_finalize (GSource *source)
   FDSource *fd_source = (FDSource *)source;
 
   if (fd_source->cancelled_tag)
-    g_signal_handler_disconnect (fd_source->cancellable,
-				 fd_source->cancelled_tag);
+    g_cancellable_disconnect (fd_source->cancellable,
+			      fd_source->cancelled_tag);
 
   if (fd_source->cancellable)
     g_object_unref (fd_source->cancellable);
@@ -723,10 +723,9 @@ __g_fd_source_new (int fd,
 
   if (cancellable)
     fd_source->cancelled_tag =
-      g_signal_connect_data (cancellable, "cancelled",
+      g_cancellable_connect (cancellable,
 			     (GCallback)fd_source_cancelled_cb,
-			     NULL, NULL,
-			     0);
+			     NULL, NULL);
   
   return source;
 }
diff --git a/daemon/gvfsbackendftp.c b/daemon/gvfsbackendftp.c
index e434122..0af9287 100644
--- a/daemon/gvfsbackendftp.c
+++ b/daemon/gvfsbackendftp.c
@@ -1316,19 +1316,21 @@ g_vfs_backend_ftp_pop_connection (GVfsBackendFtp *ftp,
 {
   FtpConnection *conn = NULL;
   GTimeVal now;
-  guint id;
+  gulong id;
+
+  if (g_cancellable_is_cancelled (job->cancellable))
+    return NULL;
 
   g_mutex_lock (ftp->mutex);
-  id = g_signal_connect (job->cancellable, 
-			       "cancelled", 
-			       G_CALLBACK (do_broadcast),
-			       ftp->cond);
+  id = g_cancellable_connect (job->cancellable,
+			      G_CALLBACK (do_broadcast),
+			      ftp->cond, NULL);
   while (conn == NULL && ftp->queue != NULL)
     {
       if (g_cancellable_is_cancelled (job->cancellable))
 	break;
-      conn = g_queue_pop_head (ftp->queue);
 
+      conn = g_queue_pop_head (ftp->queue);
       if (conn != NULL)
 	{
 	  /* Figure out if this connection had a timeout sent. If so, skip it. */
@@ -1393,7 +1395,7 @@ g_vfs_backend_ftp_pop_connection (GVfsBackendFtp *ftp,
 	  break;
 	}
     }
-  g_signal_handler_disconnect (job->cancellable, id);
+  g_cancellable_disconnect (job->cancellable, id);
 
   return conn;
 }



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