Allows to destroy a QXL object Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> --- 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 -- 2.9.3 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel