[glib] GIOScheduler: Disconnect from cancellable after job completes



commit b65194e8dfd3d9c3fabb16a189c0b326c175f9d5
Author: Colin Walters <walters verbum org>
Date:   Mon Jun 25 17:05:45 2012 -0400

    GIOScheduler: Disconnect from cancellable after job completes
    
    This was causing crashes when a cancellable was canceled after the job
    had completed.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=678576

 gio/gioscheduler.c |   49 ++++++++++++++++++++++---------------------------
 1 files changed, 22 insertions(+), 27 deletions(-)
---
diff --git a/gio/gioscheduler.c b/gio/gioscheduler.c
index b94d8dd..856e4b9 100644
--- a/gio/gioscheduler.c
+++ b/gio/gioscheduler.c
@@ -53,6 +53,7 @@ struct _GIOSchedulerJob {
 
   gint io_priority;
   GCancellable *cancellable;
+  gulong cancellable_id;
   GMainContext *context;
 };
 
@@ -68,7 +69,11 @@ static void
 g_io_job_free (GIOSchedulerJob *job)
 {
   if (job->cancellable)
-    g_object_unref (job->cancellable);
+    {
+      if (job->cancellable_id)
+	g_cancellable_disconnect (job->cancellable, job->cancellable_id);
+      g_object_unref (job->cancellable);
+    }
   g_main_context_unref (job->context);
   g_free (job);
 }
@@ -120,34 +125,18 @@ init_scheduler (gpointer arg)
 }
 
 static void
-remove_active_job (GIOSchedulerJob *job)
+on_job_canceled (GCancellable    *cancellable,
+		 gpointer         user_data)
 {
-  GIOSchedulerJob *other_job;
-  GList *l;
-  gboolean resort_jobs;
-  
-  G_LOCK (active_jobs);
-  active_jobs = g_list_delete_link (active_jobs, job->active_link);
-  
-  resort_jobs = FALSE;
-  for (l = active_jobs; l != NULL; l = l->next)
-    {
-      other_job = l->data;
-      if (other_job->io_priority >= 0 &&
-	  g_cancellable_is_cancelled (other_job->cancellable))
-	{
-	  other_job->io_priority = -1;
-	  resort_jobs = TRUE;
-	}
-    }
-  G_UNLOCK (active_jobs);
-  
-  if (resort_jobs &&
-      job_thread_pool != NULL)
+  GIOSchedulerJob *job = user_data;
+
+  job->io_priority = -1;
+  job->cancellable_id = 0;
+
+  if (job_thread_pool != NULL)
     g_thread_pool_set_sort_function (job_thread_pool,
 				     g_io_job_compare,
 				     NULL);
-
 }
 
 static void
@@ -158,7 +147,9 @@ job_destroy (gpointer data)
   if (job->destroy_notify)
     job->destroy_notify (job->data);
 
-  remove_active_job (job);
+  G_LOCK (active_jobs);
+  active_jobs = g_list_delete_link (active_jobs, job->active_link);
+  G_UNLOCK (active_jobs);
   g_io_job_free (job);
 }
 
@@ -221,7 +212,11 @@ g_io_scheduler_push_job (GIOSchedulerJobFunc  job_func,
   job->io_priority = io_priority;
     
   if (cancellable)
-    job->cancellable = g_object_ref (cancellable);
+    {
+      job->cancellable = g_object_ref (cancellable);
+      job->cancellable_id = g_cancellable_connect (job->cancellable, (GCallback)on_job_canceled,
+						   job, NULL);
+    }
 
   job->context = g_main_context_ref_thread_default ();
 



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