[libsoup/carlosgc/auth-retry-cancel] Fix runtime critical when message is cancelled after a failed auth




commit e85c8c23895e12516e3266ab22a54ec3e4ba47f9
Author: Carlos Garcia Campos <cgarcia igalia com>
Date:   Thu Sep 10 15:49:37 2020 +0200

    Fix runtime critical when message is cancelled after a failed auth
    
    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.

 libsoup/soup-session.c |  3 ++-
 tests/auth-test.c      | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+), 1 deletion(-)
---
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 ();
 


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