[libsoup/carlosgc/websockets-input-source-assert] WebSockets: do not start the input source when IO is closing



commit 07248d3d9f89d5fad4fdeffa990d8f826a115d4a
Author: Carlos Garcia Campos <cgarcia igalia com>
Date:   Tue Jan 21 11:41:37 2020 +0100

    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.

 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 2c7fc116..a4095e1c 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 b5142612..5e40cf36 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,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]