[gnome-builder/wip/chergert/debugger: 42/58] mi2: move client cleanup into dispose handler



commit d9796b1f5fb53587feba7ee6b8ebdad7c78d6bd3
Author: Christian Hergert <chergert redhat com>
Date:   Sat Mar 25 15:36:42 2017 -0700

    mi2: move client cleanup into dispose handler
    
    We want to start cleaning this stuff up earlier to break referencing
    issues. I still see a segfault when dealing with python callbacks, but
    that requires more investigation.

 contrib/mi2/mi2-client.c |   63 +++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 57 insertions(+), 6 deletions(-)
---
diff --git a/contrib/mi2/mi2-client.c b/contrib/mi2/mi2-client.c
index 630a720..a7ee629 100644
--- a/contrib/mi2/mi2-client.c
+++ b/contrib/mi2/mi2-client.c
@@ -60,6 +60,36 @@ G_DEFINE_TYPE_WITH_PRIVATE (Mi2Client, mi2_client, G_TYPE_OBJECT)
 static GParamSpec *properties [N_PROPS];
 static guint signals [N_SIGNALS];
 
+static void
+mi2_client_cancel_all_tasks (Mi2Client *self)
+{
+  Mi2ClientPrivate *priv = mi2_client_get_instance_private (self);
+  GList *list;
+
+  g_assert (MI2_IS_CLIENT (self));
+
+  g_queue_foreach (&priv->exec_commands, (GFunc)g_object_unref, NULL);
+  g_queue_clear (&priv->exec_commands);
+
+  list = priv->exec_tasks.head;
+
+  priv->exec_tasks.head = NULL;
+  priv->exec_tasks.tail = NULL;
+  priv->exec_tasks.length = 0;
+
+  for (const GList *iter = list; iter != NULL; iter = iter->next)
+    {
+      g_autoptr(GTask) task = iter->data;
+
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_CANCELLED,
+                               "The operation was cancelled");
+    }
+
+  g_list_free (list);
+}
+
 static gboolean
 mi2_client_check_ready (Mi2Client  *self,
                         GError    **error)
@@ -77,6 +107,24 @@ mi2_client_check_ready (Mi2Client  *self,
       return FALSE;
     }
 
+  if (priv->read_loop_cancellable == NULL)
+    {
+      g_set_error (error,
+                   G_IO_ERROR,
+                   G_IO_ERROR_NOT_CONNECTED,
+                   "You must call mi2_client_start_listening() first");
+      return FALSE;
+    }
+
+  if (g_cancellable_is_cancelled (priv->read_loop_cancellable))
+    {
+      g_set_error (error,
+                   G_IO_ERROR,
+                   G_IO_ERROR_CANCELLED,
+                   "The client has already been shutdown");
+      return FALSE;
+    }
+
   return TRUE;
 }
 
@@ -120,22 +168,24 @@ mi2_client_real_event (Mi2Client       *self,
 }
 
 static void
-mi2_client_finalize (GObject *object)
+mi2_client_dispose (GObject *object)
 {
   Mi2Client *self = (Mi2Client *)object;
   Mi2ClientPrivate *priv = mi2_client_get_instance_private (self);
 
+  mi2_client_cancel_all_tasks (self);
+
   g_clear_object (&priv->io_stream);
   g_clear_object (&priv->input_stream);
   g_clear_object (&priv->output_stream);
   g_clear_object (&priv->read_loop_cancellable);
 
-  g_queue_foreach (&priv->exec_tasks, (GFunc)g_object_unref, NULL);
-  g_queue_clear (&priv->exec_tasks);
-
-  g_queue_foreach (&priv->exec_commands, (GFunc)g_object_unref, NULL);
-  g_queue_clear (&priv->exec_commands);
+  G_OBJECT_CLASS (mi2_client_parent_class)->dispose (object);
+}
 
+static void
+mi2_client_finalize (GObject *object)
+{
   G_OBJECT_CLASS (mi2_client_parent_class)->finalize (object);
 }
 
@@ -183,6 +233,7 @@ mi2_client_class_init (Mi2ClientClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
+  object_class->dispose = mi2_client_dispose;
   object_class->finalize = mi2_client_finalize;
   object_class->get_property = mi2_client_get_property;
   object_class->set_property = mi2_client_set_property;


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