[gnome-todo] gtd-task: Avoid crash by using weak reference on GtdTaskList



commit f1a8e5c964a1b4939d4517aebaf0eaca05fea519
Author: Victor Toso <me victortoso com>
Date:   Tue Nov 8 22:14:04 2016 +0100

    gtd-task: Avoid crash by using weak reference on GtdTaskList
    
    The crash happens as GtdTaskList was freed but GtdTask keeps a dangling
    pointer to it. In gtd_manager_update_task(), gtd_task_get_list() is
    called returning a dangling pointer which is provided to
    gtd_task_list_get_provider(), causing the crash on GTD_IS_TASK_LIST().
    
    As documentation in gtd_task_get_list() says that it holds a weak
    reference to GtdTaskList but it did not do the weak_ref, this patch
    tries to fix that.
    
    If GtdTaskList is freed now, task_list_weak_notified() will set the
    priv->list pointer to NULL.
    
    Thread 1 "gnome-todo" received signal SIGSEGV, Segmentation fault.
    0x0000000000426aa0 in GTD_IS_TASK_LIST (ptr=0x1251b70) at gtd-task-list.h:32
          G_DECLARE_DERIVABLE_TYPE (GtdTaskList, gtd_task_list, GTD, TASK_LIST, GtdObject)
    
    (gdb) bt
     #0 in GTD_IS_TASK_LIST (ptr=0x1251b70) at gtd-task-list.h:32
     #1 in gtd_task_list_get_provider (list=0x1251b70) at gtd-task-list.c:525
     #2 in gtd_manager_update_task (manager=0x86cd00, task=0x12fc4a0)
        at engine/gtd-manager.c:607
     #3 in gtd_task_list_view__edit_task_finished (pane=0xe39f80, task=0x12fc4a0,
        user_data=0x95ef90) at gtd-task-list-view.c:686
     #4 in g_cclosure_marshal_VOID__OBJECTv (closure=0xe7feb0, return_value=0x0,
         instance=0xe39f80, args=0x7fffffff9a38, marshal_data=0x0, n_params=1,
         param_types=0x942930) at /jhbuild/glib/gobject/gmarshal.c:2102
     #5 in _g_closure_invoke_va (closure=0xe7feb0, return_value=0x0, instance=0xe39f80,
        args=0x7fffffff9a38, n_params=1, param_types=0x942930)
        at /jhbuild/glib/gobject/gclosure.c:867
     #6 in g_signal_emit_valist (instance=0xe39f80, signal_id=299, detail=0,
        var_args=0x7fffffff9a38) at /jhbuild/glib/gobject/gsignal.c:3300
     #7 in g_signal_emit (instance=0xe39f80, signal_id=299, detail=0)
        at /jhbuild/glib/gobject/gsignal.c:3447
     #8 in gtd_edit_pane_set_task (pane=0xe39f80, task=0x0) at gtd-edit-pane.c:446
     #9 in gtd_edit_pane_dispose (object=0xe39f80) at gtd-edit-pane.c:258
    
    https://bugzilla.gnome.org/show_bug.cgi?id=774120

 src/gtd-task.c |   27 ++++++++++++++++++++++-----
 1 files changed, 22 insertions(+), 5 deletions(-)
---
diff --git a/src/gtd-task.c b/src/gtd-task.c
index dc84ff4..be87322 100644
--- a/src/gtd-task.c
+++ b/src/gtd-task.c
@@ -291,11 +291,24 @@ real_remove_subtask (GtdTask *self,
 }
 
 static void
+task_list_weak_notified (gpointer  data,
+                         GObject  *where_the_object_was)
+{
+  GtdTask *task = GTD_TASK (data);
+  GtdTaskPrivate *priv = gtd_task_get_instance_private (task);
+  priv->list = NULL;
+}
+
+static void
 gtd_task_finalize (GObject *object)
 {
   GtdTask *self = (GtdTask*) object;
   GtdTaskPrivate *priv = gtd_task_get_instance_private (self);
 
+  if (priv->list)
+    g_object_weak_unref (G_OBJECT (priv->list), task_list_weak_notified, self);
+
+  priv->list = NULL;
   g_free (priv->description);
   g_object_unref (priv->component);
 
@@ -1076,11 +1089,15 @@ gtd_task_set_list (GtdTask     *task,
 
   priv = gtd_task_get_instance_private (task);
 
-  if (priv->list != list)
-    {
-      priv->list = list;
-      g_object_notify (G_OBJECT (task), "list");
-    }
+  if (priv->list == list)
+    return;
+
+  if (priv->list)
+    g_object_weak_unref (G_OBJECT (priv->list), task_list_weak_notified, task);
+
+  priv->list = list;
+  g_object_weak_ref (G_OBJECT (priv->list), task_list_weak_notified, task);
+  g_object_notify (G_OBJECT (task), "list");
 }
 
 /**


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