diff options
author | Philip Withnall <philip@tecnocode.co.uk> | 2010-12-10 22:35:57 +0000 |
---|---|---|
committer | Philip Withnall <philip@tecnocode.co.uk> | 2010-12-11 00:41:15 +0000 |
commit | 62cf2ea6a20f30bc644527e491d0b9765ccdd832 (patch) | |
tree | bb3b263199727a184531a6bb931adc6f74c4a493 | |
parent | dcc7f4b08d76c31298d6ee6225c4a278bc9996af (diff) | |
download | libgdata-62cf2ea6a20f30bc644527e491d0b9765ccdd832.tar.gz |
documents: Disconnect from the content-type notification signal
We can't change GDataDownloadStream to emit notification signals for
content-type in the download thread in the 0.6 branch, since that would be
an API break. This means that the notifications could potentially be
delivered after _gdata_documents_entry_download_document() returns. Since the
closure for the notification idle function maintains a reference to the
GDataDownloadStream, this means that the signal handler won't be disconnected
automatically once the GDataDownloadStream is unreffed in
_gdata_documents_entry_download_document(). Consequently, it's possible to get
invalid writes into random bits of memory unless we disconnect from the
content-type notification signal. This commit does that.
-rw-r--r-- | gdata/services/documents/gdata-documents-entry.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/gdata/services/documents/gdata-documents-entry.c b/gdata/services/documents/gdata-documents-entry.c index 1965a652..20a61f3e 100644 --- a/gdata/services/documents/gdata-documents-entry.c +++ b/gdata/services/documents/gdata-documents-entry.c @@ -615,6 +615,7 @@ _gdata_documents_entry_download_document (GDataDocumentsEntry *self, GDataServic GInputStream *src_stream; GFile *actual_file = NULL; GError *child_error = NULL; + gulong content_type_signal = 0; /* TODO: async version */ g_return_val_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self), NULL); @@ -646,8 +647,13 @@ _gdata_documents_entry_download_document (GDataDocumentsEntry *self, GDataServic src_stream = gdata_download_stream_new (GDATA_SERVICE (service), src_uri); if (content_type != NULL) g_signal_connect (src_stream, "notify::content-type", (GCallback) notify_content_type_cb, content_type); + g_output_stream_splice (G_OUTPUT_STREAM (dest_stream), src_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, cancellable, &child_error); + + if (content_type_signal != 0) + g_signal_handler_disconnect (src_stream, content_type_signal); + g_object_unref (src_stream); g_object_unref (dest_stream); if (child_error != NULL) { |