summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLionel Landwerlin <llandwerlin@gmail.com>2014-01-21 19:12:08 +0000
committerDan Winship <danw@gnome.org>2014-05-05 11:10:09 -0400
commit1565a4914494e56275d6ff393b90b8fb1b712708 (patch)
treef9ff2956d2421fb574ff6c866c68452b04bda675
parent24fdee7a78f9148fce173781128bd3287ca5ede1 (diff)
gio: iostream: use GTask instead of internal pointer
This fixes an infinite recursion loop when calling g_io_stream_close_async() on a SoupIOStream. https://bugzilla.gnome.org/show_bug.cgi?id=722723
-rw-r--r--gio/giostream.c49
1 files changed, 25 insertions, 24 deletions
diff --git a/gio/giostream.c b/gio/giostream.c
index e64e66cec..cd177acf0 100644
--- a/gio/giostream.c
+++ b/gio/giostream.c
@@ -73,7 +73,6 @@ enum
struct _GIOStreamPrivate {
guint closed : 1;
guint pending : 1;
- GAsyncReadyCallback outstanding_callback;
};
static gboolean g_io_stream_real_close (GIOStream *stream,
@@ -414,12 +413,25 @@ async_ready_close_callback_wrapper (GObject *source_object,
gpointer user_data)
{
GIOStream *stream = G_IO_STREAM (source_object);
+ GIOStreamClass *klass = G_IO_STREAM_GET_CLASS (stream);
+ GTask *task = user_data;
+ GError *error = NULL;
+ gboolean success;
stream->priv->closed = TRUE;
g_io_stream_clear_pending (stream);
- if (stream->priv->outstanding_callback)
- (*stream->priv->outstanding_callback) (source_object, res, user_data);
- g_object_unref (stream);
+
+ if (g_async_result_legacy_propagate_error (res, &error))
+ success = FALSE;
+ else
+ success = klass->close_finish (stream, res, &error);
+
+ if (error)
+ g_task_return_error (task, error);
+ else
+ g_task_return_boolean (task, success);
+
+ g_object_unref (task);
}
/**
@@ -452,15 +464,14 @@ g_io_stream_close_async (GIOStream *stream,
{
GIOStreamClass *class;
GError *error = NULL;
+ GTask *task;
g_return_if_fail (G_IS_IO_STREAM (stream));
+ task = g_task_new (stream, cancellable, callback, user_data);
+
if (stream->priv->closed)
{
- GTask *task;
-
- task = g_task_new (stream, cancellable, callback, user_data);
- g_task_set_source_tag (task, g_io_stream_close_async);
g_task_return_boolean (task, TRUE);
g_object_unref (task);
return;
@@ -468,17 +479,15 @@ g_io_stream_close_async (GIOStream *stream,
if (!g_io_stream_set_pending (stream, &error))
{
- g_task_report_error (stream, callback, user_data,
- g_io_stream_close_async,
- error);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
class = G_IO_STREAM_GET_CLASS (stream);
- stream->priv->outstanding_callback = callback;
- g_object_ref (stream);
+
class->close_async (stream, io_priority, cancellable,
- async_ready_close_callback_wrapper, user_data);
+ async_ready_close_callback_wrapper, task);
}
/**
@@ -499,18 +508,10 @@ g_io_stream_close_finish (GIOStream *stream,
GAsyncResult *result,
GError **error)
{
- GIOStreamClass *class;
-
g_return_val_if_fail (G_IS_IO_STREAM (stream), FALSE);
- g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
-
- if (g_async_result_legacy_propagate_error (result, error))
- return FALSE;
- else if (g_async_result_is_tagged (result, g_io_stream_close_async))
- return g_task_propagate_boolean (G_TASK (result), error);
+ g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
- class = G_IO_STREAM_GET_CLASS (stream);
- return class->close_finish (stream, result, error);
+ return g_task_propagate_boolean (G_TASK (result), error);
}