tree/node: add and use node_finish in destroy functions

We set node as dirty in {output,workspace,container}_begin_destroy
functions but this leaves destroyed pointers in server.dirty_nodes while
destroying. This can cause crashes when waking up the screen after being
turned off for a while, because we request modeset on a 10ms timer when
starting to destroy outputs. This timer could fire while we're in the
middle of destroying the output and make us try to modeset an already
freed output.

See backtrace in https://github.com/swaywm/sway/pull/8969
This commit is contained in:
llyyr 2026-03-26 22:47:53 +05:30
parent f50f78c0d9
commit 9ba2f52e4d
5 changed files with 12 additions and 0 deletions

View file

@ -60,6 +60,8 @@ const char *node_type_to_str(enum sway_node_type type);
*/ */
void node_set_dirty(struct sway_node *node); void node_set_dirty(struct sway_node *node);
void node_finish(struct sway_node *node);
bool node_is_view(struct sway_node *node); bool node_is_view(struct sway_node *node);
char *node_get_name(struct sway_node *node); char *node_get_name(struct sway_node *node);

View file

@ -530,6 +530,7 @@ void container_destroy(struct sway_container *con) {
scene_node_disown_children(con->content_tree); scene_node_disown_children(con->content_tree);
wlr_scene_node_destroy(&con->scene_tree->node); wlr_scene_node_destroy(&con->scene_tree->node);
node_finish(&con->node);
free(con); free(con);
} }

View file

@ -36,6 +36,13 @@ void node_set_dirty(struct sway_node *node) {
list_add(server.dirty_nodes, node); list_add(server.dirty_nodes, node);
} }
void node_finish(struct sway_node *node) {
int dirty_idx = list_find(server.dirty_nodes, node);
if (dirty_idx >= 0) {
list_del(server.dirty_nodes, dirty_idx);
}
}
bool node_is_view(struct sway_node *node) { bool node_is_view(struct sway_node *node) {
return node->type == N_CONTAINER && node->sway_container->view; return node->type == N_CONTAINER && node->sway_container->view;
} }

View file

@ -273,6 +273,7 @@ void output_destroy(struct sway_output *output) {
list_free(output->workspaces); list_free(output->workspaces);
list_free(output->current.workspaces); list_free(output->current.workspaces);
wlr_color_transform_unref(output->color_transform); wlr_color_transform_unref(output->color_transform);
node_finish(&output->node);
free(output); free(output);
} }

View file

@ -292,6 +292,7 @@ void workspace_destroy(struct sway_workspace *workspace) {
list_free(workspace->tiling); list_free(workspace->tiling);
list_free(workspace->current.floating); list_free(workspace->current.floating);
list_free(workspace->current.tiling); list_free(workspace->current.tiling);
node_finish(&workspace->node);
free(workspace); free(workspace);
} }