summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2011-05-23 23:08:05 +0100
committerPhilip Withnall <philip@tecnocode.co.uk>2011-05-23 23:16:08 +0100
commit6498d83db47a7d83f4bbcad7870086ae94edafbd (patch)
treef808b22b27c17d18bc31003b60528c99ee2121a7
parent400a4e74f5a506ddff07605a93aa7412262fea38 (diff)
downloadlibgdata-0-8.tar.gz
core: Don't assume that messages can't be cancelled externallylibgdata-0-8
In _gdata_service_actually_send_message() we were previously assuming that we were the only code which could cancel an in-progress message's request. This isn't true. soup_session_abort() can be called from anywhere else and will explicitly cancel all in-progress requests. This could happen if the GDataService is disposed of, which would cause the SoupSession to be disposed of, which causes it to abort all in-progress requests. Alternatively, it could happen if the GDataService's (and hence SoupSession's) proxy URI is changed. To fix this, we: • now hold a reference to the session and message in _gdata_service_actually_send_message() so that they're kept alive throughout the request; and we • no longer assume that a cancelled message was cancelled by us, removing the assertion which caused the crash in bgo#650835. Fixes: bgo#650835
-rw-r--r--gdata/gdata-service.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/gdata/gdata-service.c b/gdata/gdata-service.c
index 53b7b608..420eec22 100644
--- a/gdata/gdata-service.c
+++ b/gdata/gdata-service.c
@@ -991,6 +991,12 @@ _gdata_service_actually_send_message (SoupSession *session, SoupMessage *message
MessageData data;
gulong cancel_signal = 0, request_queued_signal = 0;
+ /* Hold references to the session and message so they can't be freed by other threads. For example, if the SoupSession was freed by another
+ * thread while we were making a request, the request would be unexpectedly cancelled. See bgo#650835 for an example of this breaking things.
+ */
+ g_object_ref (session);
+ g_object_ref (message);
+
/* Listen for cancellation */
if (cancellable != NULL) {
g_static_mutex_init (&(data.mutex));
@@ -1029,10 +1035,22 @@ _gdata_service_actually_send_message (SoupSession *session, SoupMessage *message
g_static_mutex_free (&(data.mutex));
}
- /* Set the cancellation error if applicable */
+ /* Set the cancellation error if applicable. We can't assume that our GCancellable has been cancelled just because the message has;
+ * libsoup may internally cancel messages if, for example, the proxy URI of the SoupSession is changed. */
g_assert (message->status_code != SOUP_STATUS_NONE);
- if (message->status_code == SOUP_STATUS_CANCELLED)
- g_assert (cancellable != NULL && g_cancellable_set_error_if_cancelled (cancellable, error) == TRUE);
+
+ if (message->status_code == SOUP_STATUS_CANCELLED) {
+ /* We hackily create and cancel a new GCancellable so that we can set the error using it and therefore save ourselves a translatable
+ * string and the associated maintenance. */
+ GCancellable *error_cancellable = g_cancellable_new ();
+ g_cancellable_cancel (error_cancellable);
+ g_assert (g_cancellable_set_error_if_cancelled (error_cancellable, error) == TRUE);
+ g_object_unref (error_cancellable);
+ }
+
+ /* Free things */
+ g_object_unref (message);
+ g_object_unref (session);
}
guint