[Spice-commits] server/red-qxl.c server/red-qxl.h server/red-worker.c server/red-worker.h

Frediano Ziglio fziglio at kemper.freedesktop.org
Fri Dec 2 15:54:46 UTC 2016


 server/red-qxl.c    |   25 ++++++++++++++++++++++---
 server/red-qxl.h    |    1 +
 server/red-worker.c |   40 +++++++++++++++++++++++++++++++++++++++-
 server/red-worker.h |    1 +
 4 files changed, 63 insertions(+), 4 deletions(-)

New commits:
commit 87f562d84333a1b52e00f4a478745925f287207f
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Thu Nov 24 17:19:46 2016 +0000

    Add red_qxl_destroy function
    
    Allows to destroy a QXL object
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

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..9be4b99 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,42 @@ 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);
+}
+
+/*
+ * Free the worker thread. This function should be called by RedQxl
+ * after sending a RED_WORKER_MESSAGE_CLOSE_WORKER message;
+ * failing to do so will cause a deadlock.
+ */
+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


More information about the Spice-commits mailing list