From 87e8c2ab9f3bc79befb0e3b25ec513cfd36fefe9 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Tue, 21 Jan 2020 11:41:37 +0100 Subject: [PATCH] WebSockets: do not start the input source when IO is closing We should not schedule a new read after reading the close message, since we don't expect more input. This fixes a crash due to an assert that checks that the input source is NULL when the connection is destroyed that happens when the connection is destroyed in the closed callback. Fixes #181 --- libsoup/soup-websocket-connection.c | 3 ++- tests/websocket-test.c | 33 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/libsoup/soup-websocket-connection.c b/libsoup/soup-websocket-connection.c index 2c7fc1161..a4095e1c9 100644 --- a/libsoup/soup-websocket-connection.c +++ b/libsoup/soup-websocket-connection.c @@ -1156,7 +1156,8 @@ soup_websocket_connection_read (SoupWebsocketConnection *self) return; } - soup_websocket_connection_start_input_source (self); + if (!pv->io_closing) + soup_websocket_connection_start_input_source (self); } static gboolean diff --git a/tests/websocket-test.c b/tests/websocket-test.c index b5142612e..5e40cf364 100644 --- a/tests/websocket-test.c +++ b/tests/websocket-test.c @@ -1067,6 +1067,34 @@ test_close_after_close (Test *test, g_io_stream_close (test->raw_server, NULL, NULL); } +static gboolean +on_close_unref_connection (SoupWebsocketConnection *ws, + gpointer user_data) +{ + Test *test = user_data; + + g_assert_true (test->server == ws); + g_clear_object (&test->server); + return TRUE; +} + +static void +test_server_unref_connection_on_close (Test *test, + gconstpointer data) +{ + gboolean close_event_client = FALSE; + + g_signal_connect (test->client, "closed", G_CALLBACK (on_close_set_flag), &close_event_client); + g_signal_connect (test->server, "closed", G_CALLBACK (on_close_unref_connection), test); + soup_websocket_connection_close (test->client, SOUP_WEBSOCKET_CLOSE_GOING_AWAY, "client closed"); + g_assert_cmpint (soup_websocket_connection_get_state (test->client), ==, SOUP_WEBSOCKET_STATE_CLOSING); + + WAIT_UNTIL (test->server == NULL); + WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED); + + g_assert_true (close_event_client); +} + static gpointer timeout_server_thread (gpointer user_data) { @@ -1923,6 +1951,11 @@ main (int argc, test_close_after_close, teardown_direct_connection); + g_test_add ("/websocket/soup/server-unref-connection-on-close", Test, NULL, + setup_soup_connection, + test_server_unref_connection_on_close, + teardown_soup_connection); + g_test_add ("/websocket/direct/protocol-negotiate", Test, NULL, NULL, test_protocol_negotiate_direct, -- GitLab