sway

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

commit 357d341f8fd68cd6902ea029a46baf5ce3411336
parent 14fbe9242fd43c5f58b2b55ec11bd1ead9dab3eb
Author: Kenny Levinsen <kl@kl.wtf>
Date:   Thu, 31 Jul 2025 15:44:49 +0200

tree/node: Do not mark destroying nodes as dirty

Node destruction currently runs through the transaction system such that
a particular node is only destroyed after its use in an ongoing
transaction. If a node is dirtied after the node is marked as destroying
but before it is destroyed, the pointer added to dirty_nodes would
become a dangling pointer once the node was destroyed.

Do not dirty destroying nodes, and ensure that destroying is only set
after the last dirty.

Diffstat:
Msway/tree/container.c | 2+-
Msway/tree/node.c | 2+-
Msway/tree/output.c | 2+-
Msway/tree/workspace.c | 2+-
4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/sway/tree/container.c b/sway/tree/container.c @@ -547,8 +547,8 @@ void container_begin_destroy(struct sway_container *con) { container_end_mouse_operation(con); - con->node.destroying = true; node_set_dirty(&con->node); + con->node.destroying = true; if (con->scratchpad) { root_scratchpad_remove_container(con); diff --git a/sway/tree/node.c b/sway/tree/node.c @@ -29,7 +29,7 @@ const char *node_type_to_str(enum sway_node_type type) { } void node_set_dirty(struct sway_node *node) { - if (node->dirty) { + if (node->dirty || node->destroying) { return; } node->dirty = true; diff --git a/sway/tree/output.c b/sway/tree/output.c @@ -301,8 +301,8 @@ void output_begin_destroy(struct sway_output *output) { sway_log(SWAY_DEBUG, "Destroying output '%s'", output->wlr_output->name); wl_signal_emit_mutable(&output->node.events.destroy, &output->node); - output->node.destroying = true; node_set_dirty(&output->node); + output->node.destroying = true; } struct sway_output *output_from_wlr_output(struct wlr_output *output) { diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c @@ -166,8 +166,8 @@ void workspace_begin_destroy(struct sway_workspace *workspace) { if (workspace->output) { workspace_detach(workspace); } - workspace->node.destroying = true; node_set_dirty(&workspace->node); + workspace->node.destroying = true; } void workspace_consider_destroy(struct sway_workspace *ws) {