[Spice-commits] server/red-client.c

Frediano Ziglio fziglio at kemper.freedesktop.org
Thu Aug 31 17:05:48 UTC 2017


 server/red-client.c |   19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

New commits:
commit 03e28721a2fb04fd4a4588164acf8a8132b9f8ce
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Thu Aug 24 12:25:19 2017 +0100

    red-client: Prevent RedChannelClient creation when the RedClient is being destroyed
    
    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>
    Acked-by: Christophe Fergeau <cfergeau at redhat.com>

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)


More information about the Spice-commits mailing list