[libsoup] soup-message-io: keep cancellable alive for duration of io_run_until
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libsoup] soup-message-io: keep cancellable alive for duration of io_run_until
- Date: Tue, 15 May 2012 16:23:40 +0000 (UTC)
commit dba687f01cfe5aad36c3df1b830b1e1d6ab4592d
Author: Dan Winship <danw gnome org>
Date: Tue May 15 12:20:19 2012 -0400
soup-message-io: keep cancellable alive for duration of io_run_until
io_run() passes io->cancellable to io_run_until(), but io may be
destroyed (and cancellable unreffed) before io_run_until() returns,
causing it to eventually call g_cancellable_is_cancelled() on garbage.
Fix by reffing it around the io_run_until() call (though really this
is just another example of "SoupMessageIOData needs to be
refcounted".)
Tweak misc-test to test this case.
Fixes crasher in rygel test case. Based on a patch from Ray Strode.
https://bugzilla.gnome.org/show_bug.cgi?id=676038
libsoup/soup-message-io.c | 6 +++++-
tests/misc-test.c | 18 +++++++++++++++++-
2 files changed, 22 insertions(+), 2 deletions(-)
---
diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c
index 455265e..7a554df 100644
--- a/libsoup/soup-message-io.c
+++ b/libsoup/soup-message-io.c
@@ -886,6 +886,7 @@ io_run (SoupMessage *msg, gpointer user_data)
SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
SoupMessageIOData *io = priv->io_data;
GError *error = NULL;
+ GCancellable *cancellable;
if (io->io_source) {
g_source_destroy (io->io_source);
@@ -894,11 +895,12 @@ io_run (SoupMessage *msg, gpointer user_data)
}
g_object_ref (msg);
+ cancellable = io->cancellable ? g_object_ref (io->cancellable) : NULL;
if (io_run_until (msg,
SOUP_MESSAGE_IO_STATE_DONE,
SOUP_MESSAGE_IO_STATE_DONE,
- io->cancellable, &error)) {
+ cancellable, &error)) {
soup_message_io_finished (msg);
} else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
g_clear_error (&error);
@@ -909,6 +911,8 @@ io_run (SoupMessage *msg, gpointer user_data)
}
g_object_unref (msg);
+ g_clear_object (&cancellable);
+
return FALSE;
}
diff --git a/tests/misc-test.c b/tests/misc-test.c
index 39d63d3..a2b9937 100644
--- a/tests/misc-test.c
+++ b/tests/misc-test.c
@@ -857,11 +857,20 @@ cancel_message_thread (gpointer msg)
}
static void
+set_done (SoupSession *session, SoupMessage *msg, gpointer user_data)
+{
+ gboolean *done = user_data;
+
+ *done = TRUE;
+}
+
+static void
do_cancel_while_reading_test_for_session (SoupSession *session)
{
SoupMessage *msg;
GThread *thread = NULL;
SoupURI *uri;
+ gboolean done = FALSE;
uri = soup_uri_new_with_base (base_uri, "/slow");
msg = soup_message_new_from_uri ("GET", uri);
@@ -875,7 +884,14 @@ do_cancel_while_reading_test_for_session (SoupSession *session)
else
thread = g_thread_new ("cancel_message_thread", cancel_message_thread, msg);
- soup_session_send_message (session, msg);
+ /* We intentionally don't use soup_session_send_message() here,
+ * because it holds an extra ref on the SoupMessageQueueItem
+ * relative to soup_session_queue_message().
+ */
+ g_object_ref (msg);
+ soup_session_queue_message (session, msg, set_done, &done);
+ while (!done)
+ g_main_context_iteration (NULL, TRUE);
if (msg->status_code != SOUP_STATUS_CANCELLED) {
debug_printf (1, " FAILED: %d %s (expected Cancelled)\n",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]