diff --git a/gio/goutputstream.c b/gio/goutputstream.c index 87b61a4ec..9e2848e37 100644 --- a/gio/goutputstream.c +++ b/gio/goutputstream.c @@ -2643,6 +2643,8 @@ g_output_stream_real_writev_finish (GOutputStream *stream, typedef struct { GInputStream *source; GOutputStreamSpliceFlags flags; + guint istream_closed : 1; + guint ostream_closed : 1; gssize n_read; gssize n_written; gsize bytes_copied; @@ -2665,11 +2667,11 @@ real_splice_async_complete_cb (GTask *task) SpliceData *op = g_task_get_task_data (task); if (op->flags & G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE && - !g_input_stream_is_closed (op->source)) + !op->istream_closed) return; if (op->flags & G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET && - !g_output_stream_is_closed (g_task_get_source_object (task))) + !op->ostream_closed) return; if (op->error != NULL) @@ -2691,8 +2693,10 @@ real_splice_async_close_input_cb (GObject *source, gpointer user_data) { GTask *task = user_data; + SpliceData *op = g_task_get_task_data (task); g_input_stream_close_finish (G_INPUT_STREAM (source), res, NULL); + op->istream_closed = TRUE; real_splice_async_complete_cb (task); } @@ -2707,6 +2711,7 @@ real_splice_async_close_output_cb (GObject *source, GError **error = (op->error == NULL) ? &op->error : NULL; g_output_stream_internal_close_finish (G_OUTPUT_STREAM (source), res, error); + op->ostream_closed = TRUE; real_splice_async_complete_cb (task); } diff --git a/gio/tests/async-splice-output-stream.c b/gio/tests/async-splice-output-stream.c index e69c4db5d..fb317b733 100644 --- a/gio/tests/async-splice-output-stream.c +++ b/gio/tests/async-splice-output-stream.c @@ -32,6 +32,7 @@ typedef enum TEST_THREADED_NONE = 0, TEST_THREADED_ISTREAM = 1, TEST_THREADED_OSTREAM = 2, + TEST_CANCEL = 4, TEST_THREADED_BOTH = TEST_THREADED_ISTREAM | TEST_THREADED_OSTREAM, } TestThreadedFlags; @@ -58,6 +59,14 @@ test_copy_chunks_splice_cb (GObject *source, bytes_spliced = g_output_stream_splice_finish (G_OUTPUT_STREAM (source), res, &error); + + if (data->flags & TEST_CANCEL) + { + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); + g_main_loop_quit (data->main_loop); + return; + } + g_assert_no_error (error); g_assert_cmpint (bytes_spliced, ==, strlen (data->data)); @@ -100,11 +109,18 @@ test_copy_chunks_start (TestThreadedFlags flags) { TestCopyChunksData data; GError *error = NULL; + GCancellable *cancellable = NULL; data.main_loop = g_main_loop_new (NULL, FALSE); data.data = "abcdefghijklmnopqrstuvwxyz"; data.flags = flags; + if (data.flags & TEST_CANCEL) + { + cancellable = g_cancellable_new (); + g_cancellable_cancel (cancellable); + } + if (data.flags & TEST_THREADED_ISTREAM) { GFile *file; @@ -150,7 +166,7 @@ test_copy_chunks_start (TestThreadedFlags flags) g_output_stream_splice_async (data.ostream, data.istream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, - G_PRIORITY_DEFAULT, NULL, + G_PRIORITY_DEFAULT, cancellable, test_copy_chunks_splice_cb, &data); /* We do not hold a ref in data struct, this is to make sure the operation @@ -158,6 +174,7 @@ test_copy_chunks_start (TestThreadedFlags flags) */ g_object_unref (data.istream); g_object_unref (data.ostream); + g_clear_object (&cancellable); g_main_loop_run (data.main_loop); g_main_loop_unref (data.main_loop); @@ -187,6 +204,12 @@ test_copy_chunks_threaded (void) test_copy_chunks_start (TEST_THREADED_BOTH); } +static void +test_cancelled (void) +{ + test_copy_chunks_start (TEST_THREADED_NONE | TEST_CANCEL); +} + int main (int argc, char *argv[]) @@ -200,6 +223,8 @@ main (int argc, test_copy_chunks_threaded_output); g_test_add_func ("/async-splice/copy-chunks-threaded", test_copy_chunks_threaded); + g_test_add_func ("/async-splice/cancelled", + test_cancelled); return g_test_run(); }