summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2020-09-10 15:49:37 +0200
committerCarlos Garcia Campos <carlosgc@gnome.org>2020-09-10 15:56:10 +0200
commite85c8c23895e12516e3266ab22a54ec3e4ba47f9 (patch)
treebb6ced71498fac12218a9fc1f8f7704269cc4b3c
parente2e6fa43bb677f33dc89f2c6a0914a88a7b1a24b (diff)
downloadlibsoup-carlosgc/auth-retry-cancel.tar.gz
Fix runtime critical when message is cancelled after a failed authcarlosgc/auth-retry-cancel
When the message is restarted due to the failed auth, we fail to properly reset the SoupSession:ostream data on the item task and we end up calling async_send_request_return_result() twice causing the following critical the second time: (auth-test:66750): libsoup-CRITICAL **: 15:48:08.156: async_send_request_return_result: assertion 'item->task != NULL' failed SoupSession:ostream data is set in item task, but we reset in item message.
-rw-r--r--libsoup/soup-session.c3
-rw-r--r--tests/auth-test.c60
2 files changed, 62 insertions, 1 deletions
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index 6d68c9fb..dd3cdc46 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -3944,7 +3944,8 @@ async_send_request_restarted (SoupMessage *msg, gpointer user_data)
SoupMessageQueueItem *item = user_data;
/* We won't be needing this, then. */
- g_object_set_data (G_OBJECT (item->msg), "SoupSession:ostream", NULL);
+ if (item->task)
+ g_object_set_data (G_OBJECT (item->task), "SoupSession:ostream", NULL);
item->io_started = FALSE;
}
diff --git a/tests/auth-test.c b/tests/auth-test.c
index 95de60c2..8295ec32 100644
--- a/tests/auth-test.c
+++ b/tests/auth-test.c
@@ -1490,6 +1490,65 @@ do_message_has_authorization_header_test (void)
soup_test_session_abort_unref (session);
}
+static void
+cancel_after_retry_authenticate (SoupSession *session,
+ SoupMessage *msg,
+ SoupAuth *auth,
+ gboolean retrying,
+ GCancellable *cancellable)
+{
+ if (retrying) {
+ soup_session_cancel_message (session, msg, SOUP_STATUS_CANCELLED);
+ g_cancellable_cancel (cancellable);
+ } else
+ soup_auth_authenticate (auth, "user1", "wrong");
+}
+
+static void
+request_send_cb (SoupSession *session,
+ GAsyncResult *result,
+ GMainLoop *loop)
+{
+ GInputStream *stream;
+ GError *error = NULL;
+
+ stream = soup_session_send_finish (session, result, &error);
+ g_assert_null (stream);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
+
+ g_main_loop_quit (loop);
+}
+
+static void
+do_cancel_after_retry_test (void)
+{
+ SoupSession *session;
+ SoupMessage *msg;
+ char *uri;
+ GCancellable *cancellable;
+ GMainLoop *loop;
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
+ cancellable = g_cancellable_new ();
+ g_signal_connect (session, "authenticate",
+ G_CALLBACK (cancel_after_retry_authenticate),
+ cancellable);
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ uri = g_strconcat (base_uri, "Digest/realm1/", NULL);
+ msg = soup_message_new ("GET", uri);
+ soup_session_send_async (session, msg, cancellable, (GAsyncReadyCallback)request_send_cb, loop);
+ g_main_loop_run (loop);
+
+ g_object_unref (msg);
+ g_object_unref (cancellable);
+ g_free (uri);
+ soup_test_session_abort_unref (session);
+}
+
int
main (int argc, char **argv)
{
@@ -1516,6 +1575,7 @@ main (int argc, char **argv)
g_test_add_func ("/auth/message-do-not-use-auth-cache", do_message_do_not_use_auth_cache_test);
g_test_add_func ("/auth/async-message-do-not-use-auth-cache", do_async_message_do_not_use_auth_cache_test);
g_test_add_func ("/auth/authorization-header-request", do_message_has_authorization_header_test);
+ g_test_add_func ("/auth/cancel-after-retry", do_cancel_after_retry_test);
ret = g_test_run ();