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.
This commit is contained in:
Kenny Levinsen 2025-07-31 15:44:49 +02:00 committed by Simon Ser
parent 14fbe9242f
commit 357d341f8f
4 changed files with 4 additions and 4 deletions

View file

@ -547,8 +547,8 @@ void container_begin_destroy(struct sway_container *con) {
container_end_mouse_operation(con); container_end_mouse_operation(con);
con->node.destroying = true;
node_set_dirty(&con->node); node_set_dirty(&con->node);
con->node.destroying = true;
if (con->scratchpad) { if (con->scratchpad) {
root_scratchpad_remove_container(con); root_scratchpad_remove_container(con);

View file

@ -29,7 +29,7 @@ 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) {
if (node->dirty) { if (node->dirty || node->destroying) {
return; return;
} }
node->dirty = true; node->dirty = true;

View file

@ -301,8 +301,8 @@ void output_begin_destroy(struct sway_output *output) {
sway_log(SWAY_DEBUG, "Destroying output '%s'", output->wlr_output->name); sway_log(SWAY_DEBUG, "Destroying output '%s'", output->wlr_output->name);
wl_signal_emit_mutable(&output->node.events.destroy, &output->node); wl_signal_emit_mutable(&output->node.events.destroy, &output->node);
output->node.destroying = true;
node_set_dirty(&output->node); node_set_dirty(&output->node);
output->node.destroying = true;
} }
struct sway_output *output_from_wlr_output(struct wlr_output *output) { struct sway_output *output_from_wlr_output(struct wlr_output *output) {

View file

@ -166,8 +166,8 @@ void workspace_begin_destroy(struct sway_workspace *workspace) {
if (workspace->output) { if (workspace->output) {
workspace_detach(workspace); workspace_detach(workspace);
} }
workspace->node.destroying = true;
node_set_dirty(&workspace->node); node_set_dirty(&workspace->node);
workspace->node.destroying = true;
} }
void workspace_consider_destroy(struct sway_workspace *ws) { void workspace_consider_destroy(struct sway_workspace *ws) {