summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/red_channel.c23
-rw-r--r--server/red_channel.h17
2 files changed, 35 insertions, 5 deletions
diff --git a/server/red_channel.c b/server/red_channel.c
index 0d74413e..9168b8ad 100644
--- a/server/red_channel.c
+++ b/server/red_channel.c
@@ -1932,10 +1932,29 @@ RedClient *red_client_new(int migrated)
pthread_mutex_init(&client->lock, NULL);
client->thread_id = pthread_self();
client->during_target_migrate = migrated;
+ client->refs = 1;
return client;
}
+RedClient *red_client_ref(RedClient *client)
+{
+ spice_assert(client);
+ client->refs++;
+ return client;
+}
+
+RedClient *red_client_unref(RedClient *client)
+{
+ if (!--client->refs) {
+ spice_debug("release client=%p", client);
+ pthread_mutex_destroy(&client->lock);
+ free(client);
+ return NULL;
+ }
+ return client;
+}
+
/* client mutex should be locked before this call */
static void red_channel_client_set_migration_seamless(RedChannelClient *rcc)
{
@@ -2012,9 +2031,7 @@ void red_client_destroy(RedClient *client)
spice_assert(rcc->send_data.size == 0);
red_channel_client_destroy(rcc);
}
-
- pthread_mutex_destroy(&client->lock);
- free(client);
+ red_client_unref(client);
}
/* client->lock should be locked */
diff --git a/server/red_channel.h b/server/red_channel.h
index ba299b66..0dd73ea8 100644
--- a/server/red_channel.h
+++ b/server/red_channel.h
@@ -561,10 +561,25 @@ struct RedClient {
is called */
int seamless_migrate;
int num_migrated_channels; /* for seamless - number of channels that wait for migrate data*/
+ int refs;
};
RedClient *red_client_new(int migrated);
+/*
+ * disconnects all the client's channels (should be called from the client's thread)
+ */
+void red_client_destroy(RedClient *client);
+
+RedClient *red_client_ref(RedClient *client);
+
+/*
+ * releases the client resources when refs == 0.
+ * We assume the red_client_derstroy was called before
+ * we reached refs==0
+ */
+RedClient *red_client_unref(RedClient *client);
+
MainChannelClient *red_client_get_main(RedClient *client);
// main should be set once before all the other channels are created
void red_client_set_main(RedClient *client, MainChannelClient *mcc);
@@ -580,7 +595,5 @@ void red_client_semi_seamless_migrate_complete(RedClient *client); /* dst side *
int red_client_during_migrate_at_target(RedClient *client);
void red_client_migrate(RedClient *client);
-// disconnects all the client's channels (should be called from the client's thread)
-void red_client_destroy(RedClient *client);
#endif