diff options
author | Carlos Garcia Campos <cgarcia@igalia.com> | 2021-06-22 17:56:39 +0200 |
---|---|---|
committer | Carlos Garcia Campos <cgarcia@igalia.com> | 2021-06-22 17:59:48 +0200 |
commit | 9a91641a1291d003cd97617079d04e08a6c59ea9 (patch) | |
tree | 47ed226728667732b1028003d2af61d47bd20e44 | |
parent | fcc79a377ec1e8e38c0554233bb565e41e0e3e94 (diff) | |
download | libsoup-9a91641a1291d003cd97617079d04e08a6c59ea9.tar.gz |
http2-io: fix a crash when a goaway frame is received while processing pending messages
We need to make sure the connection is not disconnected while we are in
io_read_ready.
-rw-r--r-- | libsoup/http1/soup-client-message-io-http1.c | 4 | ||||
-rw-r--r-- | libsoup/http1/soup-client-message-io-http1.h | 2 | ||||
-rw-r--r-- | libsoup/http2/soup-client-message-io-http2.c | 23 | ||||
-rw-r--r-- | libsoup/http2/soup-client-message-io-http2.h | 3 | ||||
-rw-r--r-- | libsoup/soup-connection.c | 8 |
5 files changed, 28 insertions, 12 deletions
diff --git a/libsoup/http1/soup-client-message-io-http1.c b/libsoup/http1/soup-client-message-io-http1.c index 46029612..129ddb4f 100644 --- a/libsoup/http1/soup-client-message-io-http1.c +++ b/libsoup/http1/soup-client-message-io-http1.c @@ -1161,12 +1161,12 @@ static const SoupClientMessageIOFuncs io_funcs = { }; SoupClientMessageIO * -soup_client_message_io_http1_new (GIOStream *stream) +soup_client_message_io_http1_new (SoupConnection *conn) { SoupClientMessageIOHTTP1 *io; io = g_slice_new0 (SoupClientMessageIOHTTP1); - io->iostream = g_object_ref (stream); + io->iostream = g_object_ref (soup_connection_get_iostream (conn)); io->istream = g_io_stream_get_input_stream (io->iostream); io->ostream = g_io_stream_get_output_stream (io->iostream); io->is_reusable = TRUE; diff --git a/libsoup/http1/soup-client-message-io-http1.h b/libsoup/http1/soup-client-message-io-http1.h index e749360d..0634df29 100644 --- a/libsoup/http1/soup-client-message-io-http1.h +++ b/libsoup/http1/soup-client-message-io-http1.h @@ -7,4 +7,4 @@ #include "soup-client-message-io.h" -SoupClientMessageIO *soup_client_message_io_http1_new (GIOStream *stream); +SoupClientMessageIO *soup_client_message_io_http1_new (SoupConnection *conn); diff --git a/libsoup/http2/soup-client-message-io-http2.c b/libsoup/http2/soup-client-message-io-http2.c index b1ae61e0..334fb8be 100644 --- a/libsoup/http2/soup-client-message-io-http2.c +++ b/libsoup/http2/soup-client-message-io-http2.c @@ -61,6 +61,7 @@ typedef enum { typedef struct { SoupClientMessageIO iface; + SoupConnection *conn; GIOStream *stream; GInputStream *istream; GOutputStream *ostream; @@ -443,6 +444,12 @@ io_read_ready (GObject *stream, return G_SOURCE_REMOVE; } + /* Mark the connection as in use to make sure it's not disconnected while + * processing pending messages, for example if a goaway is received. + */ + if (io->conn) + soup_connection_set_in_use (io->conn, TRUE); + while (nghttp2_session_want_read (io->session) && progress) { progress = io_read (io, FALSE, NULL, &error); if (progress) { @@ -454,6 +461,8 @@ io_read_ready (GObject *stream, if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { g_error_free (error); + if (io->conn) + soup_connection_set_in_use (io->conn, FALSE); return G_SOURCE_CONTINUE; } @@ -463,6 +472,8 @@ io_read_ready (GObject *stream, io->is_shutdown = TRUE; g_clear_pointer (&io->read_source, g_source_unref); + if (io->conn) + soup_connection_set_in_use (io->conn, FALSE); return G_SOURCE_REMOVE; } @@ -1560,6 +1571,9 @@ soup_client_message_io_http2_destroy (SoupClientMessageIO *iface) g_source_destroy (io->write_source); g_source_unref (io->write_source); } + + if (io->conn) + g_object_remove_weak_pointer (G_OBJECT (io->conn), (gpointer*)&io->conn); g_clear_object (&io->stream); g_clear_object (&io->close_task); g_clear_pointer (&io->session, nghttp2_session_del); @@ -1642,15 +1656,18 @@ soup_client_message_io_http2_init (SoupClientMessageIOHTTP2 *io) #define MAX_HEADER_TABLE_SIZE 65536 /* Match size used by Chromium/Firefox */ SoupClientMessageIO * -soup_client_message_io_http2_new (GIOStream *stream, guint64 connection_id) +soup_client_message_io_http2_new (SoupConnection *conn) { SoupClientMessageIOHTTP2 *io = g_new0 (SoupClientMessageIOHTTP2, 1); soup_client_message_io_http2_init (io); - io->stream = g_object_ref (stream); + io->conn = conn; + g_object_add_weak_pointer (G_OBJECT (io->conn), (gpointer*)&io->conn); + + io->stream = g_object_ref (soup_connection_get_iostream (conn)); io->istream = g_io_stream_get_input_stream (io->stream); io->ostream = g_io_stream_get_output_stream (io->stream); - io->connection_id = connection_id; + io->connection_id = soup_connection_get_id (conn); io->read_source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (io->istream), NULL); g_source_set_name (io->read_source, "Soup HTTP/2 read source"); diff --git a/libsoup/http2/soup-client-message-io-http2.h b/libsoup/http2/soup-client-message-io-http2.h index 213c38f3..50aece85 100644 --- a/libsoup/http2/soup-client-message-io-http2.h +++ b/libsoup/http2/soup-client-message-io-http2.h @@ -9,7 +9,6 @@ G_BEGIN_DECLS -SoupClientMessageIO *soup_client_message_io_http2_new (GIOStream *stream, - guint64 connection_id); +SoupClientMessageIO *soup_client_message_io_http2_new (SoupConnection *conn); G_END_DECLS diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index 24b084f4..3d06a870 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -455,10 +455,10 @@ soup_connection_create_io_data (SoupConnection *conn) switch (priv->http_version) { case SOUP_HTTP_1_0: case SOUP_HTTP_1_1: - priv->io_data = soup_client_message_io_http1_new (priv->iostream); + priv->io_data = soup_client_message_io_http1_new (conn); break; case SOUP_HTTP_2_0: - priv->io_data = soup_client_message_io_http2_new (priv->iostream, priv->id); + priv->io_data = soup_client_message_io_http2_new (conn); break; } } @@ -820,7 +820,7 @@ tunnel_handshake_ready_cb (GTlsConnection *tls_connection, soup_connection_event (conn, G_SOCKET_CLIENT_COMPLETE, NULL); g_assert (!priv->io_data); - priv->io_data = soup_client_message_io_http1_new (priv->iostream); + priv->io_data = soup_client_message_io_http1_new (conn); g_task_return_boolean (task, TRUE); } else { @@ -911,7 +911,7 @@ soup_connection_tunnel_handshake (SoupConnection *conn, soup_connection_event (conn, G_SOCKET_CLIENT_COMPLETE, NULL); g_assert (!priv->io_data); - priv->io_data = soup_client_message_io_http1_new (priv->iostream); + priv->io_data = soup_client_message_io_http1_new (conn); return TRUE; } |