[Spice-devel] [PATCH spice-server 1/4] red-client: Prevent RedChannelClient creation when the RedClient is being destroyed

Frediano Ziglio fziglio at redhat.com
Wed Aug 30 12:51:25 UTC 2017


This can happen as the connection is asynchronous so (MT main thread,
CT channel thread):
- MT you get a new connection;
- MT a connection is sent to CT;
- MT you get a disconnection of main channel;
- MT red_client_destroy is called;
- CT you attempt to add the RCC to RedClient.

Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
---
 server/red-client.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/server/red-client.c b/server/red-client.c
index 666903e3..ddfc5400 100644
--- a/server/red-client.c
+++ b/server/red-client.c
@@ -202,6 +202,7 @@ void red_client_destroy(RedClient *client)
                       client->thread_id,
                       pthread_self());
     }
+    red_client_set_disconnecting(client);
     FOREACH_CHANNEL_CLIENT(client, rcc) {
         RedChannel *channel;
         // some channels may be in other threads, so disconnection
@@ -254,6 +255,16 @@ gboolean red_client_add_channel(RedClient *client, RedChannelClient *rcc, GError
     pthread_mutex_lock(&client->lock);
 
     g_object_get(channel, "channel-type", &type, "id", &id, NULL);
+    if (client->disconnecting) {
+        g_set_error(error,
+                    SPICE_SERVER_ERROR,
+                    SPICE_SERVER_ERROR_FAILED,
+                    "Client %p got disconnected while connecting channel type %d id %d",
+                    client, type, id);
+        result = FALSE;
+        goto cleanup;
+    }
+
     if (red_client_get_channel(client, type, id)) {
         g_set_error(error,
                     SPICE_SERVER_ERROR,
@@ -347,12 +358,18 @@ gboolean red_client_seamless_migration_done_for_channel(RedClient *client)
 
 gboolean red_client_is_disconnecting(RedClient *client)
 {
-    return client->disconnecting;
+    gboolean ret;
+    pthread_mutex_lock(&client->lock);
+    ret =  client->disconnecting;
+    pthread_mutex_unlock(&client->lock);
+    return ret;
 }
 
 void red_client_set_disconnecting(RedClient *client)
 {
+    pthread_mutex_lock(&client->lock);
     client->disconnecting = TRUE;
+    pthread_mutex_unlock(&client->lock);
 }
 
 RedsState *red_client_get_server(RedClient *client)
-- 
2.13.5



More information about the Spice-devel mailing list