[evolution-data-server/wip/mcrha/soup3] ESoupSession: Add a lock around the SoupSession usage



commit 719609870e3377f6f0cc4e96b61e0e31bf2caa8e
Author: Milan Crha <mcrha redhat com>
Date:   Tue Jan 11 14:49:02 2022 +0100

    ESoupSession: Add a lock around the SoupSession usage
    
    The SoupSession in libsoup3 is completely thread unsafe.

 src/libedataserver/e-soup-session.c | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)
---
diff --git a/src/libedataserver/e-soup-session.c b/src/libedataserver/e-soup-session.c
index 8cf4af15e..286140eb4 100644
--- a/src/libedataserver/e-soup-session.c
+++ b/src/libedataserver/e-soup-session.c
@@ -43,6 +43,7 @@ G_DEFINE_QUARK (e-soup-session-error-quark, e_soup_session_error)
 
 struct _ESoupSessionPrivate {
        GMutex property_lock;
+       GRecMutex session_lock; /* libsoup3 has no thread safety */
        ESource *source;
        ENamedParameters *credentials;
 
@@ -80,6 +81,8 @@ e_soup_session_ensure_auth_usage (ESoupSession *session,
        g_return_if_fail (E_IS_SOUP_SESSION (session));
        g_return_if_fail (SOUP_IS_AUTH (soup_auth));
 
+       g_rec_mutex_lock (&session->priv->session_lock);
+
        feature = soup_session_get_feature (SOUP_SESSION (session), SOUP_TYPE_AUTH_MANAGER);
 
        auth_type = G_OBJECT_TYPE (soup_auth);
@@ -123,6 +126,8 @@ e_soup_session_ensure_auth_usage (ESoupSession *session,
        soup_auth_manager_clear_cached_credentials (auth_manager);
        soup_auth_manager_use_auth (auth_manager, g_uri, soup_auth);
 
+       g_rec_mutex_unlock (&session->priv->session_lock);
+
        if (!in_g_uri)
                g_uri_unref (g_uri);
 }
@@ -307,9 +312,13 @@ e_soup_session_maybe_prepare_auth (ESoupSession *session,
                } else if (g_strcmp0 (auth_method, "GSSAPI") == 0 && soup_auth_negotiate_supported ()) {
                        SoupSession *soup_session = SOUP_SESSION (session);
 
+                       g_rec_mutex_lock (&session->priv->session_lock);
+
                        if (!soup_session_get_feature (soup_session, SOUP_TYPE_AUTH_NEGOTIATE))
                                soup_session_add_feature_by_type (soup_session, SOUP_TYPE_AUTH_NEGOTIATE);
                        soup_session_remove_feature_by_type (soup_session, SOUP_TYPE_AUTH_BASIC);
+
+                       g_rec_mutex_unlock (&session->priv->session_lock);
                } else if (user && *user) {
                        /* Default to Basic authentication when user is filled */
                        success = e_soup_session_maybe_prepare_basic_auth (session, g_uri, message, user, 
credentials, cancellable, error);
@@ -468,6 +477,7 @@ e_soup_session_finalize (GObject *object)
        g_clear_pointer (&session->priv->ssl_certificate_pem, g_free);
 
        g_mutex_clear (&session->priv->property_lock);
+       g_rec_mutex_clear (&session->priv->session_lock);
 
        /* Chain up to parent's method. */
        G_OBJECT_CLASS (e_soup_session_parent_class)->finalize (object);
@@ -531,6 +541,7 @@ e_soup_session_init (ESoupSession *session)
        session->priv->auth_prefilled = FALSE;
 
        g_mutex_init (&session->priv->property_lock);
+       g_rec_mutex_init (&session->priv->session_lock);
 
        g_object_set (
                G_OBJECT (session),
@@ -591,11 +602,15 @@ e_soup_session_setup_logging (ESoupSession *session,
 
        g_return_if_fail (E_IS_SOUP_SESSION (session));
 
+       g_rec_mutex_lock (&session->priv->session_lock);
+
        soup_session_remove_feature_by_type (SOUP_SESSION (session), SOUP_TYPE_LOGGER);
        session->priv->log_level = SOUP_LOGGER_LOG_NONE;
 
-       if (!logging_level)
+       if (!logging_level) {
+               g_rec_mutex_unlock (&session->priv->session_lock);
                return;
+       }
 
        if (g_ascii_strcasecmp (logging_level, "all") == 0 ||
            g_ascii_strcasecmp (logging_level, "body") == 0 ||
@@ -605,12 +620,16 @@ e_soup_session_setup_logging (ESoupSession *session,
                session->priv->log_level = SOUP_LOGGER_LOG_HEADERS;
        else if (g_ascii_strcasecmp (logging_level, "min") == 0)
                session->priv->log_level = SOUP_LOGGER_LOG_MINIMAL;
-       else
+       else {
+               g_rec_mutex_unlock (&session->priv->session_lock);
                return;
+       }
 
        logger = soup_logger_new (session->priv->log_level);
        soup_session_add_feature (SOUP_SESSION (session), SOUP_SESSION_FEATURE (logger));
        g_object_unref (logger);
+
+       g_rec_mutex_unlock (&session->priv->session_lock);
 }
 
 /**
@@ -1141,6 +1160,7 @@ e_soup_session_send_message_ready_cb (GObject *source_object,
                                      gpointer user_data)
 {
        AsyncSendData *asd = user_data;
+       ESoupSession *esession;
        SoupSession *session;
        GInputStream *input_stream;
        GError *local_error = NULL;
@@ -1148,6 +1168,9 @@ e_soup_session_send_message_ready_cb (GObject *source_object,
        g_return_if_fail (asd != NULL);
 
        session = SOUP_SESSION (source_object);
+       esession = E_SOUP_SESSION (session);
+
+       g_rec_mutex_lock (&esession->priv->session_lock);
 
        input_stream = soup_session_send_finish (session, result, &local_error);
 
@@ -1168,6 +1191,8 @@ e_soup_session_send_message_ready_cb (GObject *source_object,
                }
        }
 
+       g_rec_mutex_unlock (&esession->priv->session_lock);
+
        if (local_error) {
                g_task_return_error (asd->task, local_error);
                g_clear_object (&input_stream);
@@ -1220,8 +1245,12 @@ e_soup_session_send_message (ESoupSession *session,
        g_task_set_source_tag (asd->task, e_soup_session_send_message);
        g_task_set_task_data (asd->task, asd, async_send_data_free);
 
+       g_rec_mutex_lock (&session->priv->session_lock);
+
        soup_session_send_async (SOUP_SESSION (session), message, io_priority, cancellable,
                e_soup_session_send_message_ready_cb, asd);
+
+       g_rec_mutex_unlock (&session->priv->session_lock);
 }
 
 /**
@@ -1341,8 +1370,12 @@ e_soup_session_send_message_sync (ESoupSession *session,
                        return NULL;
                }
 
+               g_rec_mutex_lock (&session->priv->session_lock);
+
                input_stream = soup_session_send (SOUP_SESSION (session), message, cancellable, &local_error);
 
+               g_rec_mutex_unlock (&session->priv->session_lock);
+
                if (input_stream) {
                        if (SOUP_STATUS_IS_REDIRECTION (soup_message_get_status (message))) {
                                /* libsoup uses 20, but the constant is not in any public header */


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