From e3333be150200eba59220ad1ff82c3e3507bf78c Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Mon, 18 Apr 2022 15:53:01 +0200 Subject: http2: make message IO thread safe nghttp2 session can't be used by multiple threads at the same time, so we need to ensure that only messages from the same thread share the connection. Connections in idle state can be reused from other threads, though but we need to ensure all the pending IO is completed before switching to another thread. When the connection switches to IN_USE state, the current thread becomes the owner of the connection IO. In the case of HTTP/2 there might be session IO not related to a particular message, in that case a thread with no default context is considered synchronous and all IO that is not explicitly sync or async will be sync. --- libsoup/soup-connection.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'libsoup/soup-connection.c') diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index 0c9788b9..64ee4afa 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -47,6 +47,7 @@ typedef struct { GTlsCertificate *tls_client_cert; GCancellable *cancellable; + GThread *owner; } SoupConnectionPrivate; G_DEFINE_FINAL_TYPE_WITH_PRIVATE (SoupConnection, soup_connection, G_TYPE_OBJECT) @@ -96,6 +97,7 @@ soup_connection_init (SoupConnection *conn) priv->http_version = SOUP_HTTP_1_1; priv->force_http_version = G_MAXUINT8; + priv->owner = g_thread_self (); } static void @@ -1136,8 +1138,12 @@ soup_connection_set_in_use (SoupConnection *conn, if (in_use) { g_atomic_int_inc (&priv->in_use); - if (g_atomic_int_compare_and_exchange (&priv->state, SOUP_CONNECTION_IDLE, SOUP_CONNECTION_IN_USE)) + if (g_atomic_int_compare_and_exchange (&priv->state, SOUP_CONNECTION_IDLE, SOUP_CONNECTION_IN_USE)) { + priv->owner = g_thread_self (); + soup_client_message_io_owner_changed (priv->io_data); g_object_notify_by_pspec (G_OBJECT (conn), properties[PROP_STATE]); + } + return; } @@ -1350,3 +1356,11 @@ soup_connection_is_reusable (SoupConnection *conn) return priv->io_data && soup_client_message_io_is_reusable (priv->io_data); } + +GThread * +soup_connection_get_owner (SoupConnection *conn) +{ + SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn); + + return priv->owner; +} -- cgit v1.2.1