From 0985de0bc6fbfb7778b95803beb3f0c22734db84 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 12 Oct 2026 18:23:25 +0000 Subject: [PATCH] For tree mode, hold a reference to prompt and other bits across command to avoid crashing when killing the session with the mode's pane. GitHub issue 5728. --- mode-tree.c | 35 ++++++++++++++++++++--------------- window-tree.c | 12 +++++------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/mode-tree.c b/mode-tree.c index 222047f61..011294aec 100644 --- a/mode-tree.c +++ b/mode-tree.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mode-tree.c,v 1.103 2026/09/24 18:59:00 nicm Exp $ */ +/* $OpenBSD: mode-tree.c,v 1.104 2026/10/12 18:23:25 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott @@ -701,8 +701,17 @@ mode_tree_build(struct mode_tree_data *mtd) static void mode_tree_remove_ref(struct mode_tree_data *mtd) { - if (--mtd->references == 0) - free(mtd); + if (--mtd->references != 0) + return; + + mode_tree_clear_prompt(mtd); + mode_tree_free_items(&mtd->children); + mode_tree_clear_lines(mtd); + screen_free(&mtd->screen); + + free(mtd->search); + free(mtd->filter); + free(mtd); } void @@ -713,14 +722,6 @@ mode_tree_free(struct mode_tree_data *mtd) if (mtd->zoomed == 0) server_unzoom_window(wp->window); - mode_tree_clear_prompt(mtd); - mode_tree_free_items(&mtd->children); - mode_tree_clear_lines(mtd); - screen_free(&mtd->screen); - - free(mtd->search); - free(mtd->filter); - mtd->dead = 1; mode_tree_remove_ref(mtd); } @@ -1095,7 +1096,7 @@ mode_tree_prompt_accept(struct cmdq_item *item, void *data) struct client *c = cmdq_get_client(item); key_code key = 'y'; - if (mtd->prompt != NULL && c != NULL) + if (!mtd->dead && mtd->prompt != NULL && c != NULL) mode_tree_key(mtd, c, &key, NULL, NULL, NULL); mode_tree_remove_ref(mtd); @@ -1122,7 +1123,6 @@ mode_tree_prompt_free_callback(void *data) mtp->mtd->prompt_data = NULL; if (mtp->freecb != NULL) mtp->freecb(mtp->data); - mode_tree_remove_ref(mtp->mtd); free(mtp); } @@ -1152,8 +1152,6 @@ mode_tree_set_prompt(struct mode_tree_data *mtd, struct client *c, mtp->inputcb = inputcb; mtp->freecb = freecb; mtp->data = data; - - mtd->references++; mtd->prompt_top = options_get_number(oo, "status-position") == 0; memset(&pd, 0, sizeof pd); @@ -1524,6 +1522,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, if (mtd->prompt != NULL) { redraw = 0; prompt = mtd->prompt; + mtd->references++; mtp = mtd->prompt_data; if (mtp != NULL) @@ -1548,6 +1547,11 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, } } else result = prompt_key(prompt, *key, &redraw); + if (mtd->dead) { + mode_tree_remove_ref(mtd); + *key = KEYC_NONE; + return (1); + } if (mtd->prompt_data == mtp && mtp != NULL) mtp->c = NULL; @@ -1563,6 +1567,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, mode_tree_draw(mtd); mtd->wp->flags |= PANE_REDRAW; } + mode_tree_remove_ref(mtd); if (result != PROMPT_KEY_NOT_HANDLED) { *key = KEYC_NONE; return (0); diff --git a/window-tree.c b/window-tree.c index 49f9bbecc..b6388d92d 100644 --- a/window-tree.c +++ b/window-tree.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window-tree.c,v 1.96 2026/08/25 07:23:30 nicm Exp $ */ +/* $OpenBSD: window-tree.c,v 1.97 2026/10/12 18:23:25 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott @@ -1344,12 +1344,10 @@ window_tree_kill_current_callback(struct client *c, void *modedata, if (tolower((u_char) s[0]) != 'y' || s[1] != '\0') return (PROMPT_CLOSE); + data->references++; window_tree_kill_each(data, mode_tree_get_current(mtd), c, KEYC_NONE); server_renumber_all(); - - data->references++; cmdq_append(c, cmdq_get_callback(window_tree_command_done, data)); - return (PROMPT_CLOSE); } @@ -1365,12 +1363,10 @@ window_tree_kill_tagged_callback(struct client *c, void *modedata, if (tolower((u_char) s[0]) != 'y' || s[1] != '\0') return (PROMPT_CLOSE); + data->references++; mode_tree_each_tagged(mtd, window_tree_kill_each, c, KEYC_NONE, 1); server_renumber_all(); - - data->references++; cmdq_append(c, cmdq_get_callback(window_tree_command_done, data)); - return (PROMPT_CLOSE); } @@ -1453,6 +1449,8 @@ window_tree_key(struct window_mode_entry *wme, struct client *c, item = mode_tree_get_current(data->data); finished = mode_tree_key(data->data, c, &key, m, &x, &y); + if (data->dead) + return; again: if (item != (new_item = mode_tree_get_current(data->data))) {