From 3f065cf7892824919e440ab899bfadef52e857cd Mon Sep 17 00:00:00 2001 From: nicm Date: Sun, 5 Jul 2026 18:37:57 +0000 Subject: [PATCH] Add a window pane reference count. --- tmux.h | 4 ++++ window.c | 49 ++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/tmux.h b/tmux.h index 3e5a4eae5..ddcb96146 100644 --- a/tmux.h +++ b/tmux.h @@ -1231,6 +1231,7 @@ struct visible_ranges { /* Child window structure. */ struct window_pane { u_int id; + int references; u_int active_point; struct window *window; @@ -1262,6 +1263,7 @@ struct window_pane { #define PANE_THEMECHANGED 0x2000 #define PANE_UNSEENCHANGES 0x4000 #define PANE_REDRAWSCROLLBAR 0x8000 +#define PANE_DESTROYED 0x10000 bitstr_t *sync_dirty; u_int sync_dirty_size; @@ -3603,6 +3605,8 @@ void window_pane_stack_remove(struct window_panes *, void window_set_name(struct window *, const char *, int); void window_add_ref(struct window *, const char *); void window_remove_ref(struct window *, const char *); +void window_pane_add_ref(struct window_pane *, const char *); +void window_pane_remove_ref(struct window_pane *, const char *); void winlink_clear_flags(struct winlink *); int winlink_shuffle_up(struct session *, struct winlink *, int); int window_pane_start_input(struct window_pane *, diff --git a/window.c b/window.c index 93cb1cc74..8035e6b40 100644 --- a/window.c +++ b/window.c @@ -73,6 +73,7 @@ struct window_pane_input_data { static struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int); static void window_pane_destroy(struct window_pane *); +static void window_pane_free(struct window_pane *); static void window_pane_scrollbar_timer(int, short, void *); static void window_pane_full_size_offset(struct window_pane *wp, int *xoff, int *yoff, u_int *sx, u_int *sy); @@ -421,6 +422,25 @@ window_remove_ref(struct window *w, const char *from) window_destroy(w); } +void +window_pane_add_ref(struct window_pane *wp, const char *from) +{ + wp->references++; + log_debug("%s: %%%u %s, now %d", __func__, wp->id, from, + wp->references); +} + +void +window_pane_remove_ref(struct window_pane *wp, const char *from) +{ + wp->references--; + log_debug("%s: %%%u %s, now %d", __func__, wp->id, from, + wp->references); + + if (wp->references == 0) + window_pane_free(wp); +} + void window_set_name(struct window *w, const char *new_name, int untrusted) { @@ -1073,6 +1093,7 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit) char host[HOST_NAME_MAX + 1]; wp = xcalloc(1, sizeof *wp); + wp->references = 1; wp->window = w; wp->options = options_create(w->options); wp->flags = PANE_STYLECHANGED; @@ -1201,25 +1222,28 @@ window_pane_destroy(struct window_pane *wp) spawn_editor_finish(wp); window_pane_clear_prompt(wp); + RB_REMOVE(window_pane_tree, &all_window_panes, wp); + wp->flags |= PANE_DESTROYED; window_pane_free_modes(wp); screen_write_clear_dirty(wp); - free(wp->searchstr); if (wp->fd != -1) { bufferevent_free(wp->event); + wp->event = NULL; close(wp->fd); + wp->fd = -1; } - if (wp->ictx != NULL) + if (wp->ictx != NULL) { input_free(wp->ictx); - - screen_free(&wp->status_screen); - - screen_free(&wp->base); + wp->ictx = NULL; + } if (wp->pipe_fd != -1) { bufferevent_free(wp->pipe_event); + wp->pipe_event = NULL; close(wp->pipe_fd); + wp->pipe_fd = -1; } if (event_initialized(&wp->resize_timer)) @@ -1230,7 +1254,18 @@ window_pane_destroy(struct window_pane *wp) event_del(&wp->sb_auto_timer); window_pane_clear_resizes(wp, NULL); - RB_REMOVE(window_pane_tree, &all_window_panes, wp); + window_pane_remove_ref(wp, __func__); +} + +static void +window_pane_free(struct window_pane *wp) +{ + log_debug("pane %%%u freed (%d references)", wp->id, wp->references); + + free(wp->searchstr); + + screen_free(&wp->status_screen); + screen_free(&wp->base); options_free(wp->options); free((void *)wp->cwd);