From 3c36571db03ae6bcb2741bfe581c43518ea4457a Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Fri, 26 Aug 2022 12:44:03 +0200 Subject: server: fix crash when HTTP/2 connection is closed early On connection disconnect the io data is destroyed, which can happen in the middle of a read or write operation. --- .../server/http2/soup-server-message-io-http2.c | 29 +++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/libsoup/server/http2/soup-server-message-io-http2.c b/libsoup/server/http2/soup-server-message-io-http2.c index f8b54b80..2e32b0aa 100644 --- a/libsoup/server/http2/soup-server-message-io-http2.c +++ b/libsoup/server/http2/soup-server-message-io-http2.c @@ -347,17 +347,25 @@ static gboolean io_write_ready (GObject *stream, SoupServerMessageIOHTTP2 *io) { + SoupServerConnection *conn = io->conn; GError *error = NULL; - while (nghttp2_session_want_write (io->session) && !error) + g_object_ref (conn); + + while (!error && soup_server_connection_get_io_data (conn) == (SoupServerMessageIO *)io && nghttp2_session_want_write (io->session)) io_write (io, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { g_error_free (error); + g_object_unref (conn); return G_SOURCE_CONTINUE; } + if (error && soup_server_connection_get_io_data (conn) == (SoupServerMessageIO *)io) + h2_debug (io, NULL, "[SESSION] IO error: %s", error->message); + g_clear_error (&error); + g_object_unref (conn); g_clear_pointer (&io->write_source, g_source_unref); return G_SOURCE_REMOVE; @@ -366,12 +374,15 @@ io_write_ready (GObject *stream, static void io_try_write (SoupServerMessageIOHTTP2 *io) { + SoupServerConnection *conn = io->conn; GError *error = NULL; if (io->write_source) return; - while (nghttp2_session_want_write (io->session) && !error) + g_object_ref (conn); + + while (!error && soup_server_connection_get_io_data (conn) == (SoupServerMessageIO *)io && nghttp2_session_want_write (io->session)) io_write (io, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { @@ -382,7 +393,11 @@ io_try_write (SoupServerMessageIOHTTP2 *io) g_source_attach (io->write_source, g_main_context_get_thread_default ()); } + if (error && soup_server_connection_get_io_data (conn) == (SoupServerMessageIO *)io) + h2_debug (io, NULL, "[SESSION] IO error: %s", error->message); + g_clear_error (&error); + g_object_unref (conn); } static gboolean @@ -402,18 +417,26 @@ static gboolean io_read_ready (GObject *stream, SoupServerMessageIOHTTP2 *io) { + SoupServerConnection *conn = io->conn; gboolean progress = TRUE; GError *error = NULL; - while (nghttp2_session_want_read (io->session) && progress) + g_object_ref (conn); + + while (progress && soup_server_connection_get_io_data (conn) == (SoupServerMessageIO *)io && nghttp2_session_want_read (io->session)) progress = io_read (io, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { g_error_free (error); + g_object_unref (conn); return G_SOURCE_CONTINUE; } + if (error && soup_server_connection_get_io_data (conn) == (SoupServerMessageIO *)io) + h2_debug (io, NULL, "[SESSION] IO error: %s", error->message); + g_clear_error (&error); + g_object_unref (conn); return G_SOURCE_REMOVE; } -- cgit v1.2.1