Allows to destroy a QXL object

Signed-off-by: Frediano Ziglio <fzig...@redhat.com>
---
 server/red-qxl.c    | 25 ++++++++++++++++++++++---
 server/red-qxl.h    |  1 +
 server/red-worker.c | 35 ++++++++++++++++++++++++++++++++++-
 server/red-worker.h |  1 +
 4 files changed, 58 insertions(+), 4 deletions(-)

diff --git a/server/red-qxl.c b/server/red-qxl.c
index 19cff95..de0546f 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -58,6 +58,7 @@ struct QXLState {
     QXLDevSurfaceCreate surface_create;
     unsigned int max_monitors;
     RedsState *reds;
+    RedWorker *worker;
 
     pthread_mutex_t scanout_mutex;
     SpiceMsgDisplayGlScanoutUnix scanout;
@@ -1006,11 +1007,29 @@ void red_qxl_init(RedsState *reds, QXLInstance *qxl)
     client_display_cbs.disconnect = red_qxl_disconnect_display_peer;
     client_display_cbs.migrate = red_qxl_display_migrate;
 
-    // TODO: reference and free
-    RedWorker *worker = red_worker_new(qxl, &client_cursor_cbs,
+    qxl_state->worker = red_worker_new(qxl, &client_cursor_cbs,
                                        &client_display_cbs);
 
-    red_worker_run(worker);
+    red_worker_run(qxl_state->worker);
+}
+
+void red_qxl_destroy(QXLInstance *qxl)
+{
+    spice_return_if_fail(qxl->st != NULL && qxl->st->dispatcher != NULL);
+
+    QXLState *qxl_state = qxl->st;
+
+    /* send message to close thread */
+    RedWorkerMessageClose message;
+    dispatcher_send_message(qxl_state->dispatcher,
+                            RED_WORKER_MESSAGE_CLOSE_WORKER,
+                            &message);
+    red_worker_free(qxl_state->worker);
+    g_object_unref(qxl_state->dispatcher);
+    /* this must be done after calling red_worker_free */
+    qxl->st = NULL;
+    pthread_mutex_destroy(&qxl_state->scanout_mutex);
+    free(qxl_state);
 }
 
 Dispatcher *red_qxl_get_dispatcher(QXLInstance *qxl)
diff --git a/server/red-qxl.h b/server/red-qxl.h
index 65357b1..7743124 100644
--- a/server/red-qxl.h
+++ b/server/red-qxl.h
@@ -24,6 +24,7 @@
 typedef struct AsyncCommand AsyncCommand;
 
 void red_qxl_init(SpiceServer *reds, QXLInstance *qxl);
+void red_qxl_destroy(QXLInstance *qxl);
 
 void red_qxl_on_ic_change(QXLInstance *qxl, SpiceImageCompression ic);
 void red_qxl_on_sv_change(QXLInstance *qxl, int sv);
diff --git a/server/red-worker.c b/server/red-worker.c
index d699bd6..5dac0ec 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -1410,7 +1410,6 @@ static void *red_worker_main(void *arg)
     g_main_loop_unref(loop);
     worker->loop = NULL;
 
-    /* FIXME: free worker, and join threads */
     return NULL;
 }
 
@@ -1435,3 +1434,37 @@ bool red_worker_run(RedWorker *worker)
 
     return r == 0;
 }
+
+static void red_worker_close_channel(RedChannel *channel)
+{
+    red_channel_reset_thread_id(channel);
+    red_channel_destroy(channel);
+}
+
+void red_worker_free(RedWorker *worker)
+{
+    RedsState *reds = red_qxl_get_server(worker->qxl->st);
+
+    /* prevent any possible future attempt to connect to new clients */
+    reds_unregister_channel(reds, RED_CHANNEL(worker->cursor_channel));
+    reds_unregister_channel(reds, RED_CHANNEL(worker->display_channel));
+
+    pthread_join(worker->thread, NULL);
+
+    red_worker_close_channel(RED_CHANNEL(worker->cursor_channel));
+    worker->cursor_channel = NULL;
+    red_worker_close_channel(RED_CHANNEL(worker->display_channel));
+    worker->display_channel = NULL;
+
+    if (worker->dispatch_watch) {
+        worker->core.watch_remove(&worker->core, worker->dispatch_watch);
+    }
+
+    g_main_context_unref(worker->core.main_context);
+
+    if (worker->record) {
+        red_record_free(worker->record);
+    }
+    memslot_info_destroy(&worker->mem_slots);
+    free(worker);
+}
diff --git a/server/red-worker.h b/server/red-worker.h
index 53b92b3..d5b5a78 100644
--- a/server/red-worker.h
+++ b/server/red-worker.h
@@ -29,5 +29,6 @@ RedWorker* red_worker_new(QXLInstance *qxl,
                           const ClientCbs *client_cursor_cbs,
                           const ClientCbs *client_display_cbs);
 bool       red_worker_run(RedWorker *worker);
+void red_worker_free(RedWorker *worker);
 
 #endif
-- 
git-series 0.9.1
_______________________________________________
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Reply via email to