diff options
author | Carlos Garcia Campos <cgarcia@igalia.com> | 2022-04-18 15:53:01 +0200 |
---|---|---|
committer | Carlos Garcia Campos <cgarcia@igalia.com> | 2022-06-08 12:36:17 +0200 |
commit | e3333be150200eba59220ad1ff82c3e3507bf78c (patch) | |
tree | 9427978bec4c07c2d67cccbbb1d96616f2465acf /libsoup/soup-connection.c | |
parent | 522f8c5030da689d745558fb1fd02504d60d86ac (diff) | |
download | libsoup-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.c | 16 |
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; +} |