[evolution/gnome-3-18] Bug 758665 - Hangs auto-saving mail with big attachments



commit 86b512e165d561f8295e426e42ea106df753987f
Author: Milan Crha <mcrha redhat com>
Date:   Wed Nov 25 18:33:43 2015 +0100

    Bug 758665 - Hangs auto-saving mail with big attachments

 modules/composer-autosave/e-autosave-utils.c |   72 +++++++++++++------------
 1 files changed, 37 insertions(+), 35 deletions(-)
---
diff --git a/modules/composer-autosave/e-autosave-utils.c b/modules/composer-autosave/e-autosave-utils.c
index f9db63f..2e83b2a 100644
--- a/modules/composer-autosave/e-autosave-utils.c
+++ b/modules/composer-autosave/e-autosave-utils.c
@@ -183,13 +183,16 @@ load_snapshot_loaded_cb (GFile *snapshot_file,
 }
 
 static void
-save_snapshot_splice_cb (GOutputStream *output_stream,
+save_snapshot_splice_cb (CamelDataWrapper *data_wrapper,
                          GAsyncResult *result,
                          GSimpleAsyncResult *simple)
 {
        GError *local_error = NULL;
 
-       g_output_stream_splice_finish (output_stream, result, &local_error);
+       g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
+       g_return_if_fail (g_task_is_valid (result, data_wrapper));
+
+       g_task_propagate_int (G_TASK (result), &local_error);
 
        if (local_error != NULL)
                g_simple_async_result_take_error (simple, local_error);
@@ -199,15 +202,38 @@ save_snapshot_splice_cb (GOutputStream *output_stream,
 }
 
 static void
+write_message_to_stream_thread (GTask *task,
+                               gpointer source_object,
+                               gpointer task_data,
+                               GCancellable *cancellable)
+{
+       GOutputStream *output_stream;
+       gssize bytes_written;
+       GError *local_error = NULL;
+
+       output_stream = task_data;
+
+       bytes_written = camel_data_wrapper_decode_to_output_stream_sync (
+               CAMEL_DATA_WRAPPER (source_object),
+               output_stream, cancellable, &local_error);
+
+       g_output_stream_close (output_stream, cancellable, local_error ? NULL : &local_error);
+
+       if (local_error != NULL) {
+               g_task_return_error (task, local_error);
+       } else {
+               g_task_return_int (task, bytes_written);
+       }
+}
+
+static void
 save_snapshot_get_message_cb (EMsgComposer *composer,
                               GAsyncResult *result,
                               GSimpleAsyncResult *simple)
 {
        SaveContext *context;
        CamelMimeMessage *message;
-       GInputStream *input_stream;
-       CamelStream *camel_stream;
-       GByteArray *buffer;
+       GTask *task;
        GError *local_error = NULL;
 
        context = g_simple_async_result_get_op_res_gpointer (simple);
@@ -225,38 +251,14 @@ save_snapshot_get_message_cb (EMsgComposer *composer,
 
        g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
 
-       /* Decode the message to an in-memory buffer.  We have to do this
-        * because CamelStreams are synchronous-only, and using threads is
-        * dangerous because CamelDataWrapper is not reentrant. */
-       buffer = g_byte_array_new ();
-       camel_stream = camel_stream_mem_new ();
-       camel_stream_mem_set_byte_array (
-               CAMEL_STREAM_MEM (camel_stream), buffer);
-       camel_data_wrapper_decode_to_stream_sync (
-               CAMEL_DATA_WRAPPER (message), camel_stream, NULL, NULL);
-       g_object_unref (camel_stream);
+       task = g_task_new (message, context->cancellable, (GAsyncReadyCallback) save_snapshot_splice_cb, 
simple);
 
-       g_object_unref (message);
+       g_task_set_task_data (task, g_object_ref (context->output_stream), g_object_unref);
 
-       /* Load the buffer into a GMemoryInputStream. */
-       input_stream = g_memory_input_stream_new ();
-       if (buffer->len > 0)
-               g_memory_input_stream_add_data (
-                       G_MEMORY_INPUT_STREAM (input_stream),
-                       buffer->data, (gssize) buffer->len,
-                       (GDestroyNotify) g_free);
-       g_byte_array_free (buffer, FALSE);
-
-       /* Splice the input and output streams. */
-       g_output_stream_splice_async (
-               context->output_stream, input_stream,
-               G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
-               G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
-               G_PRIORITY_DEFAULT, context->cancellable,
-               (GAsyncReadyCallback) save_snapshot_splice_cb,
-               simple);
-
-       g_object_unref (input_stream);
+       g_task_run_in_thread (task, write_message_to_stream_thread);
+
+       g_object_unref (task);
+       g_object_unref (message);
 }
 
 static void


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