summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2022-08-26 12:44:03 +0200
committerCarlos Garcia Campos <cgarcia@igalia.com>2022-08-31 11:09:26 +0200
commit3c36571db03ae6bcb2741bfe581c43518ea4457a (patch)
treeeb5fe1cd43684450f441758f24d8c5ecd0d7278d
parent75a765a64a1beccd0b7ff145085d025b49c65c4d (diff)
downloadlibsoup-3c36571db03ae6bcb2741bfe581c43518ea4457a.tar.gz
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.
-rw-r--r--libsoup/server/http2/soup-server-message-io-http2.c29
1 files 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;
}