From 98691297e1f434bd14266891a04b338dfde483ff Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 16 Oct 2026 14:26:08 +0000 Subject: [PATCH] Clear stale pane references correctly when respawning windows, GitHub issue 5757 from Alejandro Pacheco. --- screen-redraw.c | 12 +++++++++--- spawn.c | 3 ++- window.c | 33 ++++++++++++++++++++++----------- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/screen-redraw.c b/screen-redraw.c index 8bcd1e01a..59bfa89c0 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: screen-redraw.c,v 1.169 2026/10/16 07:59:06 nicm Exp $ */ +/* $OpenBSD: screen-redraw.c,v 1.170 2026/10/16 14:26:08 nicm Exp $ */ /* * Copyright (c) 2026 Nicholas Marriott @@ -1096,11 +1096,17 @@ redraw_client_has_window(struct client *c, struct window *w) return (c->redraw_scene != NULL && c->redraw_scene->w == w); } -/* Mark a window's cached redraw scenes as out of date. */ +/* + * Mark a window's cached redraw scenes as out of date. Generations are unique + * across all windows so a scene can never match a new window that reuses the + * address of a freed one. + */ void redraw_invalidate_scene(struct window *w) { - w->redraw_scene_generation++; + static uint64_t next_generation; + + w->redraw_scene_generation = ++next_generation; } /* Free all pending damage for a window. */ diff --git a/spawn.c b/spawn.c index 19bd14a7d..8aefd6c04 100644 --- a/spawn.c +++ b/spawn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: spawn.c,v 1.57 2026/10/08 07:50:05 nicm Exp $ */ +/* $OpenBSD: spawn.c,v 1.58 2026/10/16 14:26:08 nicm Exp $ */ /* * Copyright (c) 2019 Nicholas Marriott @@ -142,6 +142,7 @@ spawn_window(struct spawn_context *sc, char **cause) } } + window_unzoom(w, 1); sc->wp0 = TAILQ_FIRST(&w->panes); TAILQ_REMOVE(&w->panes, sc->wp0, entry); diff --git a/window.c b/window.c index 8456085cc..560518c84 100644 --- a/window.c +++ b/window.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window.c,v 1.387 2026/10/16 11:34:49 bket Exp $ */ +/* $OpenBSD: window.c,v 1.388 2026/10/16 14:26:08 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -447,6 +447,7 @@ window_create(u_int sx, u_int sy, u_int xpixel, u_int ypixel) w->id = next_window_id++; RB_INSERT(windows, &windows, w); + redraw_invalidate_scene(w); if (gettimeofday(&w->creation_time, NULL) != 0) fatal("gettimeofday failed"); @@ -1189,6 +1190,19 @@ window_add_pane(struct window *w, struct window_pane *other, u_int hlimit, return (wp); } +static void +window_forget_pane(struct window *w, struct window_pane *wp) +{ + if (wp == marked_pane.wp) + server_clear_marked(); + if (wp == w->modal_last) + w->modal_last = NULL; + if (wp == w->was_zoomed) + w->was_zoomed = NULL; + window_pane_stack_remove(&w->last_panes, wp); + redraw_invalidate_scene(w); +} + void window_lost_pane(struct window *w, struct window_pane *wp) { @@ -1196,14 +1210,8 @@ window_lost_pane(struct window *w, struct window_pane *wp) log_debug("%s: @%u pane %%%u", __func__, w->id, wp->id); - if (wp == marked_pane.wp) - server_clear_marked(); - if (wp == w->modal_last) - w->modal_last = NULL; - if (wp == w->was_zoomed) - w->was_zoomed = NULL; + window_forget_pane(w, wp); - window_pane_stack_remove(&w->last_panes, wp); if (wp == w->active) { lastwp = NULL; if (wp == w->modal) { @@ -1226,10 +1234,8 @@ window_lost_pane(struct window *w, struct window_pane *wp) window_fire_pane_changed(w, w->active, wp); window_update_focus(w); } - } else if (wp == w->modal) { + } else if (wp == w->modal) w->modal = w->modal_last = NULL; - } - redraw_invalidate_scene(w); } void @@ -1357,6 +1363,11 @@ window_destroy_panes(struct window *w) while (!TAILQ_EMPTY(&w->panes)) { wp = TAILQ_FIRST(&w->panes); + window_forget_pane(w, wp); + if (wp == w->active) + w->active = NULL; + if (wp == w->modal) + w->modal = NULL; TAILQ_REMOVE(&w->panes, wp, entry); TAILQ_REMOVE(&w->z_index, wp, zentry); window_pane_destroy(wp);