From f9ce8749dc4e4f4991aa336aba7137455aa67327 Mon Sep 17 00:00:00 2001 From: Brian Ashworth Date: Fri, 13 Dec 2019 00:06:48 -0500 Subject: [PATCH] input/keyboard: defer wlr_keyboard_group destroy This defers the destruction of wlr_keyboard_groups until idle. This is to prevent the keyboard group's keyboard from being destroyed in the middle of handling a keyboard event. This would occur when changing the keymap of the last keyboard in a group with a keyboard binding. The prevents crashing when attempting to update the xkb state of the keyboard group's keyboard. The sway_keyboard_group is still immediately destroyed so that the group is no longer used --- sway/input/keyboard.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index cac713ad..f71a7909 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -659,6 +659,10 @@ static bool keymaps_match(struct xkb_keymap *km1, struct xkb_keymap *km2) { return result; } +static void destroy_empty_wlr_keyboard_group(void *data) { + wlr_keyboard_group_destroy(data); +} + static void sway_keyboard_group_remove(struct sway_keyboard *keyboard) { struct sway_input_device *device = keyboard->seat_device->input_device; struct wlr_keyboard *wlr_keyboard = device->wlr_device->keyboard; @@ -681,7 +685,11 @@ static void sway_keyboard_group_remove(struct sway_keyboard *keyboard) { free(sway_group->seat_device->input_device); free(sway_group->seat_device); free(sway_group); - wlr_keyboard_group_destroy(wlr_group); + + // To prevent use-after-free conditions when handling key events, defer + // freeing the wlr_keyboard_group until idle + wl_event_loop_add_idle(server.wl_event_loop, + destroy_empty_wlr_keyboard_group, wlr_group); } }