[libgdata] core: Write upload chunks in an idle handler to avoid stack overflow



commit e795f559327b3f208d768a4461ca1829e0f44693
Author: Philip Withnall <philip tecnocode co uk>
Date:   Wed Jul 3 19:38:07 2013 +0100

    core: Write upload chunks in an idle handler to avoid stack overflow
    
    Otherwise the used stack size would be proportional to the number of
    chunks uploaded by GDataUploadStream, and hence stack overflow could
    potentially occur.

 gdata/gdata-upload-stream.c |   30 ++++++++++++++++++++++++++++--
 1 files changed, 28 insertions(+), 2 deletions(-)
---
diff --git a/gdata/gdata-upload-stream.c b/gdata/gdata-upload-stream.c
index 8597e5b..2cbc9b4 100644
--- a/gdata/gdata-upload-stream.c
+++ b/gdata/gdata-upload-stream.c
@@ -1073,10 +1073,32 @@ wrote_headers_cb (SoupMessage *message, GDataUploadStream *self)
        write_next_chunk (self, message);
 }
 
+typedef struct {
+       GDataUploadStream *upload_stream;
+       SoupMessage *message;
+} WriteNextChunkData;
+
+static void
+write_next_chunk_data_free (WriteNextChunkData *data)
+{
+       g_object_unref (data->message);
+       g_object_unref (data->upload_stream);
+       g_slice_free (WriteNextChunkData, data);
+}
+
+static gboolean
+write_next_chunk_cb (gpointer user_data)
+{
+       WriteNextChunkData *data = user_data;
+       write_next_chunk (data->upload_stream, data->message);
+       return FALSE;
+}
+
 static void
 wrote_body_data_cb (SoupMessage *message, SoupBuffer *buffer, GDataUploadStream *self)
 {
        GDataUploadStreamPrivate *priv = self->priv;
+       WriteNextChunkData *data;
 
        /* Signal the main thread that the chunk has been written */
        g_mutex_lock (&(priv->write_mutex));
@@ -1091,8 +1113,12 @@ wrote_body_data_cb (SoupMessage *message, SoupBuffer *buffer, GDataUploadStream
        g_cond_signal (&(priv->write_cond));
        g_mutex_unlock (&(priv->write_mutex));
 
-       /* Send the next chunk to libsoup */
-       write_next_chunk (self, message);
+       /* Send the next chunk to libsoup. Do so in an idle callback to avoid overflowing the stack. */
+       data = g_slice_new (WriteNextChunkData);
+       data->message = g_object_ref (message);
+       data->upload_stream = g_object_ref (self);
+
+       g_idle_add_full (G_PRIORITY_DEFAULT, write_next_chunk_cb, data, (GDestroyNotify) 
write_next_chunk_data_free);
 }
 
 static gpointer


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