Do not add the display state to the vnc list, if the initialization failed. Add vnc_display_free(), to free the display state and associated data in such case. The function is meant to be public and reused in the following changes.
Signed-off-by: Marc-André Lureau <[email protected]> --- ui/keymaps.h | 1 + ui/keymaps.c | 13 ++++++++++--- ui/vnc.c | 30 ++++++++++++++++++++++++++---- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/ui/keymaps.h b/ui/keymaps.h index 3d52c0882a1..e8917e56404 100644 --- a/ui/keymaps.h +++ b/ui/keymaps.h @@ -54,6 +54,7 @@ typedef struct kbd_layout_t kbd_layout_t; kbd_layout_t *init_keyboard_layout(const name2keysym_t *table, const char *language, Error **errp); +void kbd_layout_free(kbd_layout_t *k); int keysym2scancode(kbd_layout_t *k, int keysym, QKbdState *kbd, bool down); int keycode_is_keypad(kbd_layout_t *k, int keycode); diff --git a/ui/keymaps.c b/ui/keymaps.c index 2359dbfe7e6..d1b3f43dc8a 100644 --- a/ui/keymaps.c +++ b/ui/keymaps.c @@ -178,6 +178,14 @@ out: return ret; } +void kbd_layout_free(kbd_layout_t *k) +{ + if (!k) { + return; + } + g_hash_table_unref(k->hash); + g_free(k); +} kbd_layout_t *init_keyboard_layout(const name2keysym_t *table, const char *language, Error **errp) @@ -185,10 +193,9 @@ kbd_layout_t *init_keyboard_layout(const name2keysym_t *table, kbd_layout_t *k; k = g_new0(kbd_layout_t, 1); - k->hash = g_hash_table_new(NULL, NULL); + k->hash = g_hash_table_new_full(NULL, NULL, NULL, g_free); if (parse_keyboard_layout(k, table, language, errp) < 0) { - g_hash_table_unref(k->hash); - g_free(k); + kbd_layout_free(k); return NULL; } return k; diff --git a/ui/vnc.c b/ui/vnc.c index 763b13acbde..115ff8a988e 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -3421,6 +3421,8 @@ static void vmstate_change_handler(void *opaque, bool running, RunState state) update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE); } +static void vnc_display_free(VncDisplay *vd); + void vnc_display_init(const char *id, Error **errp) { VncDisplay *vd; @@ -3430,8 +3432,9 @@ void vnc_display_init(const char *id, Error **errp) } vd = g_malloc0(sizeof(*vd)); + qemu_mutex_init(&vd->mutex); vd->id = g_strdup(id); - QTAILQ_INSERT_TAIL(&vnc_displays, vd, next); + vd->dcl.ops = &dcl_ops; QTAILQ_INIT(&vd->clients); vd->expires = TIME_MAX; @@ -3445,22 +3448,22 @@ void vnc_display_init(const char *id, Error **errp) } if (!vd->kbd_layout) { + vnc_display_free(vd); return; } vd->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE; vd->connections_limit = 32; - qemu_mutex_init(&vd->mutex); vnc_start_worker_thread(); - vd->dcl.ops = &dcl_ops; register_displaychangelistener(&vd->dcl); vd->kbd = qkbd_state_init(vd->dcl.con); vd->vmstate_handler_entry = qemu_add_vm_change_state_handler( &vmstate_change_handler, vd); -} + QTAILQ_INSERT_TAIL(&vnc_displays, vd, next); +} static void vnc_display_close(VncDisplay *vd) { @@ -3504,6 +3507,25 @@ static void vnc_display_close(VncDisplay *vd) #endif } +static void vnc_display_free(VncDisplay *vd) +{ + if (!vd) { + return; + } + vnc_display_close(vd); + unregister_displaychangelistener(&vd->dcl); + qkbd_state_free(vd->kbd); + qemu_del_vm_change_state_handler(vd->vmstate_handler_entry); + kbd_layout_free(vd->kbd_layout); + qemu_mutex_destroy(&vd->mutex); + if (QTAILQ_IN_USE(vd, next)) { + QTAILQ_REMOVE(&vnc_displays, vd, next); + } + g_free(vd->id); + g_free(vd); +} + + int vnc_display_password(const char *id, const char *password, Error **errp) { VncDisplay *vd = vnc_display_find(id); -- 2.53.0
