[glib/glib-2-30] Don't close stream twice when splicing
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/glib-2-30] Don't close stream twice when splicing
- Date: Mon, 19 Sep 2011 08:23:39 +0000 (UTC)
commit 7b812c434388f0fc3cbbb67df5ab9f7db3a138ed
Author: Philip Withnall <philip tecnocode co uk>
Date: Mon Sep 19 10:13:52 2011 +0200
Don't close stream twice when splicing
Ensure that the output/target stream in a g_output_stream_splice_async()
operation is marked as closed if G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET is
passed to g_output_stream_splice_async(). This removes the possibility of
local FDs being closed twice because the stream's not marked as closed.
This is implemented by calling g_output_stream_close() from within
g_output_stream_splice_async() instead of calling the stream's close_fn()
directly.
Closes: bgo#659324
(cherry picked from commit fe27bf003764e453cd15cab67e8a99fcda84db1d)
gio/goutputstream.c | 88 ++++++++++++++++++++++++++++++--------------------
1 files changed, 53 insertions(+), 35 deletions(-)
---
diff --git a/gio/goutputstream.c b/gio/goutputstream.c
index 8132caf..afe135c 100644
--- a/gio/goutputstream.c
+++ b/gio/goutputstream.c
@@ -95,6 +95,9 @@ static void g_output_stream_real_close_async (GOutputStream *s
static gboolean g_output_stream_real_close_finish (GOutputStream *stream,
GAsyncResult *result,
GError **error);
+static gboolean _g_output_stream_close_internal (GOutputStream *stream,
+ GCancellable *cancellable,
+ GError **error);
static void
g_output_stream_finalize (GObject *object)
@@ -459,9 +462,7 @@ g_output_stream_real_splice (GOutputStream *stream,
if (flags & G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET)
{
/* But write errors on close are bad! */
- if (class->close_fn &&
- !class->close_fn (stream, cancellable, error))
- res = FALSE;
+ res = _g_output_stream_close_internal (stream, cancellable, error);
}
if (res)
@@ -470,6 +471,54 @@ g_output_stream_real_splice (GOutputStream *stream,
return -1;
}
+/* Must always be called inside
+ * g_output_stream_set_pending()/g_output_stream_clear_pending(). */
+static gboolean
+_g_output_stream_close_internal (GOutputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GOutputStreamClass *class;
+ gboolean res;
+
+ if (stream->priv->closed)
+ return TRUE;
+
+ class = G_OUTPUT_STREAM_GET_CLASS (stream);
+
+ stream->priv->closing = TRUE;
+
+ if (cancellable)
+ g_cancellable_push_current (cancellable);
+
+ if (class->flush)
+ res = class->flush (stream, cancellable, error);
+ else
+ res = TRUE;
+
+ if (!res)
+ {
+ /* flushing caused the error that we want to return,
+ * but we still want to close the underlying stream if possible
+ */
+ if (class->close_fn)
+ class->close_fn (stream, cancellable, NULL);
+ }
+ else
+ {
+ res = TRUE;
+ if (class->close_fn)
+ res = class->close_fn (stream, cancellable, error);
+ }
+
+ if (cancellable)
+ g_cancellable_pop_current (cancellable);
+
+ stream->priv->closing = FALSE;
+ stream->priv->closed = TRUE;
+
+ return res;
+}
/**
* g_output_stream_close:
@@ -514,49 +563,18 @@ g_output_stream_close (GOutputStream *stream,
GCancellable *cancellable,
GError **error)
{
- GOutputStreamClass *class;
gboolean res;
g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
- class = G_OUTPUT_STREAM_GET_CLASS (stream);
-
if (stream->priv->closed)
return TRUE;
if (!g_output_stream_set_pending (stream, error))
return FALSE;
- stream->priv->closing = TRUE;
-
- if (cancellable)
- g_cancellable_push_current (cancellable);
+ res = _g_output_stream_close_internal (stream, cancellable, error);
- if (class->flush)
- res = class->flush (stream, cancellable, error);
- else
- res = TRUE;
-
- if (!res)
- {
- /* flushing caused the error that we want to return,
- * but we still want to close the underlying stream if possible
- */
- if (class->close_fn)
- class->close_fn (stream, cancellable, NULL);
- }
- else
- {
- res = TRUE;
- if (class->close_fn)
- res = class->close_fn (stream, cancellable, error);
- }
-
- if (cancellable)
- g_cancellable_pop_current (cancellable);
-
- stream->priv->closing = FALSE;
- stream->priv->closed = TRUE;
g_output_stream_clear_pending (stream);
return res;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]