[evolution-data-server/wip/mcrha/soup3] Make sure GInputStream received from libsoup3 is consumed in the same thread



commit f747a4ea7c76bafbf7336d3935cbf0ec0295e861
Author: Milan Crha <mcrha redhat com>
Date:   Thu May 5 18:30:11 2022 +0200

    Make sure GInputStream received from libsoup3 is consumed in the same thread

 src/calendar/backends/http/e-cal-backend-http.c | 48 +++++++++++--------------
 src/libedataserver/e-soup-session.c             |  8 +++++
 2 files changed, 28 insertions(+), 28 deletions(-)
---
diff --git a/src/calendar/backends/http/e-cal-backend-http.c b/src/calendar/backends/http/e-cal-backend-http.c
index 34ba531e5..246334aa2 100644
--- a/src/calendar/backends/http/e-cal-backend-http.c
+++ b/src/calendar/backends/http/e-cal-backend-http.c
@@ -37,7 +37,7 @@ struct _ECalBackendHttpPrivate {
        ESoupSession *session;
 
        SoupMessage *message;
-       GInputStream *input_stream;
+       gchar *icalstring;
        GRecMutex conn_lock;
        GHashTable *components; /* gchar *uid ~> ICalComponent * */
        gint64 hsts_until_time;
@@ -202,14 +202,14 @@ ecb_http_connect_sync (ECalMetaBackend *meta_backend,
 
        g_rec_mutex_lock (&cbhttp->priv->conn_lock);
 
-       if (cbhttp->priv->message && cbhttp->priv->input_stream) {
+       if (cbhttp->priv->message && cbhttp->priv->icalstring) {
                g_rec_mutex_unlock (&cbhttp->priv->conn_lock);
                return TRUE;
        }
 
        source = e_backend_get_source (E_BACKEND (meta_backend));
 
-       g_clear_object (&cbhttp->priv->input_stream);
+       g_clear_pointer (&cbhttp->priv->icalstring, g_free);
        g_clear_object (&cbhttp->priv->message);
 
        uri = ecb_http_dup_uri (cbhttp);
@@ -296,15 +296,19 @@ ecb_http_connect_sync (ECalMetaBackend *meta_backend,
                        uri, local_error ? local_error->message : _("Unknown error"));
        }
 
+       if (success) {
+               cbhttp->priv->icalstring = ecb_http_read_stream_sync (input_stream,
+                       soup_message_headers_get_content_length (soup_message_get_response_headers 
(message)), cancellable, error);
+               success =  cbhttp->priv->icalstring != NULL;
+       }
+
        if (success) {
                cbhttp->priv->message = message;
-               cbhttp->priv->input_stream = input_stream;
                cbhttp->priv->hsts_until_time = ecb_http_extract_hsts_until_time (cbhttp);
 
                *out_auth_result = E_SOURCE_AUTHENTICATION_ACCEPTED;
        } else {
                g_clear_object (&message);
-               g_clear_object (&input_stream);
 
                if (*out_auth_result != E_SOURCE_AUTHENTICATION_REQUIRED &&
                    *out_auth_result != E_SOURCE_AUTHENTICATION_REJECTED)
@@ -312,6 +316,7 @@ ecb_http_connect_sync (ECalMetaBackend *meta_backend,
        }
 
        g_rec_mutex_unlock (&cbhttp->priv->conn_lock);
+       g_clear_object (&input_stream);
        g_clear_error (&local_error);
        g_free (uri);
 
@@ -332,7 +337,7 @@ ecb_http_disconnect_sync (ECalMetaBackend *meta_backend,
 
        g_rec_mutex_lock (&cbhttp->priv->conn_lock);
 
-       g_clear_object (&cbhttp->priv->input_stream);
+       g_clear_pointer (&cbhttp->priv->icalstring, g_free);
        g_clear_object (&cbhttp->priv->message);
 
        if (cbhttp->priv->session)
@@ -361,7 +366,6 @@ ecb_http_get_changes_sync (ECalMetaBackend *meta_backend,
                           GError **error)
 {
        ECalBackendHttp *cbhttp;
-       gchar *icalstring;
        ICalCompIter *iter = NULL;
        ICalComponent *maincomp, *subcomp;
        ICalComponentKind backend_kind;
@@ -380,7 +384,7 @@ ecb_http_get_changes_sync (ECalMetaBackend *meta_backend,
 
        g_rec_mutex_lock (&cbhttp->priv->conn_lock);
 
-       if (!cbhttp->priv->message || !cbhttp->priv->input_stream) {
+       if (!cbhttp->priv->message || !cbhttp->priv->icalstring) {
                g_rec_mutex_unlock (&cbhttp->priv->conn_lock);
                g_propagate_error (error, EC_ERROR (E_CLIENT_ERROR_REPOSITORY_OFFLINE));
                return FALSE;
@@ -408,27 +412,15 @@ ecb_http_get_changes_sync (ECalMetaBackend *meta_backend,
 
        *out_new_sync_tag = g_strdup (new_etag);
 
-       icalstring = ecb_http_read_stream_sync (cbhttp->priv->input_stream,
-               soup_message_headers_get_content_length (soup_message_get_response_headers 
(cbhttp->priv->message)), cancellable, error);
-
        g_rec_mutex_unlock (&cbhttp->priv->conn_lock);
 
-       if (!icalstring) {
-               /* The error is already set */
-               e_cal_meta_backend_empty_cache_sync (meta_backend, cancellable, NULL);
-               ecb_http_disconnect_sync (meta_backend, cancellable, NULL);
-               return FALSE;
-       }
-
        /* Skip the UTF-8 marker at the beginning of the string */
-       if (((guchar) icalstring[0]) == 0xEF &&
-           ((guchar) icalstring[1]) == 0xBB &&
-           ((guchar) icalstring[2]) == 0xBF)
-               maincomp = i_cal_parser_parse_string (icalstring + 3);
+       if (((guchar) cbhttp->priv->icalstring[0]) == 0xEF &&
+           ((guchar) cbhttp->priv->icalstring[1]) == 0xBB &&
+           ((guchar) cbhttp->priv->icalstring[2]) == 0xBF)
+               maincomp = i_cal_parser_parse_string (cbhttp->priv->icalstring + 3);
        else
-               maincomp = i_cal_parser_parse_string (icalstring);
-
-       g_free (icalstring);
+               maincomp = i_cal_parser_parse_string (cbhttp->priv->icalstring);
 
        if (!maincomp) {
                g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Bad file format."));
@@ -537,8 +529,8 @@ ecb_http_get_changes_sync (ECalMetaBackend *meta_backend,
                g_object_unref (maincomp);
        }
 
-       if (!success)
-               ecb_http_disconnect_sync (meta_backend, cancellable, NULL);
+       /* Always disconnect, to free the resources needed to download the iCalendar file */
+       ecb_http_disconnect_sync (meta_backend, cancellable, NULL);
 
        return success;
 }
@@ -675,7 +667,7 @@ e_cal_backend_http_dispose (GObject *object)
        g_rec_mutex_lock (&cbhttp->priv->conn_lock);
 
        g_clear_object (&cbhttp->priv->message);
-       g_clear_object (&cbhttp->priv->input_stream);
+       g_clear_pointer (&cbhttp->priv->icalstring, g_free);
 
        if (cbhttp->priv->session)
                soup_session_abort (SOUP_SESSION (cbhttp->priv->session));
diff --git a/src/libedataserver/e-soup-session.c b/src/libedataserver/e-soup-session.c
index d27640905..80b11b3dd 100644
--- a/src/libedataserver/e-soup-session.c
+++ b/src/libedataserver/e-soup-session.c
@@ -1288,6 +1288,10 @@ e_soup_session_send_message (ESoupSession *session,
  * The optional @out_certificate_pem and @out_certificate_errors are set,
  * when provided, only if the operation failed with a TLS/SSL error.
  *
+ * Make sure the #GInputStream is read and freed from the same thread,
+ * and with the same thread default main context, which this function
+ * was called from, otherwise it can break libsoup3.
+ *
  * Returns: (transfer full) (nullable): a #GInputStream for reading the response body, or %NULL on error
  *
  * Since: 3.48
@@ -1345,6 +1349,10 @@ e_soup_session_send_message_finish (ESoupSession *session,
  * e_soup_session_check_result() to verify that the receive had
  * been finished properly.
  *
+ * Make sure the #GInputStream is read and freed from the same thread,
+ * and with the same thread default main context, which this function
+ * was called from, otherwise it can break libsoup3.
+ *
  * Returns: (transfer full): A newly allocated #GInputStream,
  *    that can be used to read from the URI pointed to by @message.
  *    Free it with g_object_unref(), when no longer needed.


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