[gnome-builder] jsonrpc: fix async failures causing reference issues
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] jsonrpc: fix async failures causing reference issues
- Date: Sat, 18 Mar 2017 09:28:46 +0000 (UTC)
commit e8834bccc7a7b0ed997b7ba156b50e126da222d4
Author: Christian Hergert <chergert redhat com>
Date: Fri Mar 17 16:09:46 2017 -0700
jsonrpc: fix async failures causing reference issues
We need to be very careful about the ordering and how we dispatch callbacks
so that ownership is preserved across the callback chain.
contrib/jsonrpc-glib/jsonrpc-client.c | 43 +++++++++++++++++++++++----------
libide/langserv/ide-langserv-client.c | 26 ++++++++++++++++++-
2 files changed, 54 insertions(+), 15 deletions(-)
---
diff --git a/contrib/jsonrpc-glib/jsonrpc-client.c b/contrib/jsonrpc-glib/jsonrpc-client.c
index 3e58e46..6d834ce 100644
--- a/contrib/jsonrpc-glib/jsonrpc-client.c
+++ b/contrib/jsonrpc-glib/jsonrpc-client.c
@@ -474,26 +474,34 @@ jsonrpc_client_new (GIOStream *io_stream)
}
static void
-jsonrpc_client_call_notify_completed (GTask *task,
- GParamSpec *pspec,
- gpointer user_data)
+jsonrpc_client_remove_from_invocatoins (JsonrpcClient *self,
+ GTask *task)
{
- JsonrpcClientPrivate *priv;
- JsonrpcClient *self;
+ JsonrpcClientPrivate *priv = jsonrpc_client_get_instance_private (self);
gpointer id;
+ g_assert (JSONRPC_IS_CLIENT (self));
g_assert (G_IS_TASK (task));
- g_assert (pspec != NULL);
- g_assert (g_str_equal (pspec->name, "completed"));
- self = g_task_get_source_object (task);
- priv = jsonrpc_client_get_instance_private (self);
id = g_task_get_task_data (task);
g_hash_table_remove (priv->invocations, id);
}
static void
+jsonrpc_client_call_notify_completed (JsonrpcClient *self,
+ GParamSpec *pspec,
+ GTask *task)
+{
+ g_assert (JSONRPC_IS_CLIENT (self));
+ g_assert (pspec != NULL);
+ g_assert (g_str_equal (pspec->name, "completed"));
+ g_assert (G_IS_TASK (task));
+
+ jsonrpc_client_remove_from_invocatoins (self, task);
+}
+
+static void
jsonrpc_client_call_write_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
@@ -501,12 +509,20 @@ jsonrpc_client_call_write_cb (GObject *object,
JsonrpcOutputStream *stream = (JsonrpcOutputStream *)object;
g_autoptr(GTask) task = user_data;
g_autoptr(GError) error = NULL;
+ JsonrpcClient *self;
g_assert (JSONRPC_IS_OUTPUT_STREAM (stream));
+ g_assert (G_IS_ASYNC_RESULT (result));
g_assert (G_IS_TASK (task));
+ self = g_task_get_source_object (task);
+ g_assert (JSONRPC_IS_CLIENT (self));
+
+ jsonrpc_client_remove_from_invocatoins (self, task);
+
if (!jsonrpc_output_stream_write_message_finish (stream, result, &error))
{
+ jsonrpc_client_panic (self, error);
g_task_return_error (task, g_steal_pointer (&error));
return;
}
@@ -838,10 +854,11 @@ jsonrpc_client_call_async (JsonrpcClient *self,
return;
}
- g_signal_connect (task,
- "notify::completed",
- G_CALLBACK (jsonrpc_client_call_notify_completed),
- NULL);
+ g_signal_connect_object (task,
+ "notify::completed",
+ G_CALLBACK (jsonrpc_client_call_notify_completed),
+ self,
+ G_CONNECT_SWAPPED);
id = ++priv->sequence;
diff --git a/libide/langserv/ide-langserv-client.c b/libide/langserv/ide-langserv-client.c
index 5493b0b..f2532cb 100644
--- a/libide/langserv/ide-langserv-client.c
+++ b/libide/langserv/ide-langserv-client.c
@@ -946,6 +946,19 @@ ide_langserv_client_start (IdeLangservClient *self)
}
static void
+ide_langserv_client_close_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(IdeLangservClient) self = user_data;
+ JsonrpcClient *client = (JsonrpcClient *)object;
+
+ g_assert (IDE_IS_LANGSERV_CLIENT (self));
+
+ jsonrpc_client_close_finish (client, result, NULL);
+}
+
+static void
ide_langserv_client_shutdown_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
@@ -961,8 +974,11 @@ ide_langserv_client_shutdown_cb (GObject *object,
if (!jsonrpc_client_call_finish (client, result, NULL, &error))
g_warning ("%s", error->message);
-
- jsonrpc_client_close_async (client, NULL, NULL, NULL);
+ else
+ jsonrpc_client_close_async (client,
+ NULL,
+ ide_langserv_client_close_cb,
+ g_object_ref (self));
IDE_EXIT;
}
@@ -1004,6 +1020,7 @@ ide_langserv_client_call_cb (GObject *object,
g_assert (JSONRPC_IS_CLIENT (client));
g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (G_IS_TASK (task));
if (!jsonrpc_client_call_finish (client, result, &return_value, &error))
{
@@ -1040,6 +1057,11 @@ ide_langserv_client_call_async (IdeLangservClient *self,
IDE_ENTRY;
+ g_return_if_fail (IDE_IS_LANGSERV_CLIENT (self));
+ g_return_if_fail (method != NULL);
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (!priv->rpc_client || JSONRPC_IS_CLIENT (priv->rpc_client));
+
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, ide_langserv_client_call_async);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]