sway

i3-compatible Wayland compositor
git clone https://git.awy.one/sway
Log | Files | Refs | README | LICENSE

commit ab2e1f5817a8024366fcb02285c978c5fef7dae1
parent 53126cdceb6dbf6ee163ca0db960cf3900870075
Author: Ferdinand Bachmann <ferdinand.bachmann@yrlf.at>
Date:   Tue, 18 Feb 2025 23:14:06 +0100

tree/container: remove event listeners on destroy

Change begin_destroy to remove event listeners before the final destroy,
since otherwise event listeners would be removed twice, which crashes.

This fixes a crash in wlroots listener checks. See #8509.

Diffstat:
Minclude/sway/tree/container.h | 1+
Msway/tree/container.c | 19+++++++++++++++++--
2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h @@ -95,6 +95,7 @@ struct sway_container { struct wl_listener output_enter; struct wl_listener output_leave; + struct wl_listener output_handler_destroy; struct sway_container_state current; struct sway_container_state pending; diff --git a/sway/tree/container.c b/sway/tree/container.c @@ -50,6 +50,14 @@ static void handle_output_leave( } } +static void handle_destroy( + struct wl_listener *listener, void *data) { + struct sway_container *con = wl_container_of( + listener, con, output_handler_destroy); + + container_begin_destroy(con); +} + static bool handle_point_accepts_input( struct wlr_scene_buffer *buffer, double *x, double *y) { return false; @@ -135,6 +143,9 @@ struct sway_container *container_create(struct sway_view *view) { c->output_leave.notify = handle_output_leave; wl_signal_add(&c->output_handler->events.output_leave, &c->output_leave); + c->output_handler_destroy.notify = handle_destroy; + wl_signal_add(&c->output_handler->node.events.destroy, + &c->output_handler_destroy); c->output_handler->point_accepts_input = handle_point_accepts_input; } } @@ -508,8 +519,6 @@ void container_destroy(struct sway_container *con) { if (con->view && con->view->container == con) { con->view->container = NULL; - wl_list_remove(&con->output_enter.link); - wl_list_remove(&con->output_leave.link); wlr_scene_node_destroy(&con->output_handler->node); if (con->view->destroying) { view_destroy(con->view); @@ -552,6 +561,12 @@ void container_begin_destroy(struct sway_container *con) { if (con->pending.parent || con->pending.workspace) { container_detach(con); } + + if (con->view && con->view->container == con) { + wl_list_remove(&con->output_enter.link); + wl_list_remove(&con->output_leave.link); + wl_list_remove(&con->output_handler_destroy.link); + } } void container_reap_empty(struct sway_container *con) {