summaryrefslogtreecommitdiff
path: root/libsoup/soup-connection.c
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2022-04-18 15:53:01 +0200
committerCarlos Garcia Campos <cgarcia@igalia.com>2022-06-08 12:36:17 +0200
commite3333be150200eba59220ad1ff82c3e3507bf78c (patch)
tree9427978bec4c07c2d67cccbbb1d96616f2465acf /libsoup/soup-connection.c
parent522f8c5030da689d745558fb1fd02504d60d86ac (diff)
downloadlibsoup-e3333be150200eba59220ad1ff82c3e3507bf78c.tar.gz
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.
Diffstat (limited to 'libsoup/soup-connection.c')
-rw-r--r--libsoup/soup-connection.c16
1 files changed, 15 insertions, 1 deletions
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;
+}