Pull format allocation outside of loop for control subs, from Conor

Taylor in GitHub issue 4848.
This commit is contained in:
nicm
2026-02-16 08:42:57 +00:00
parent f218463976
commit c9162837a0

120
control.c
View File

@@ -847,15 +847,13 @@ control_stop(struct client *c)
/* Check session subscription. */ /* Check session subscription. */
static void static void
control_check_subs_session(struct client *c, struct control_sub *csub) control_check_subs_session(struct client *c, struct control_sub *csub,
struct format_tree *ft)
{ {
struct session *s = c->session; struct session *s = c->session;
struct format_tree *ft;
char *value; char *value;
ft = format_create_defaults(NULL, c, s, NULL, NULL);
value = format_expand(ft, csub->format); value = format_expand(ft, csub->format);
format_free(ft);
if (csub->last != NULL && strcmp(value, csub->last) == 0) { if (csub->last != NULL && strcmp(value, csub->last) == 0) {
free(value); free(value);
@@ -916,24 +914,17 @@ control_check_subs_pane(struct client *c, struct control_sub *csub)
} }
} }
/* Check all panes subscription. */ /* Check all-panes subscription for a pane. */
static void static void
control_check_subs_all_panes(struct client *c, struct control_sub *csub) control_check_subs_all_panes_one(struct client *c, struct control_sub *csub,
struct format_tree *ft, struct winlink *wl, struct window_pane *wp)
{ {
struct session *s = c->session; struct session *s = c->session;
struct window_pane *wp; struct window *w = wl->window;
struct window *w;
struct winlink *wl;
struct format_tree *ft;
char *value; char *value;
struct control_sub_pane *csp, find; struct control_sub_pane *csp, find;
RB_FOREACH(wl, winlinks, &s->windows) {
w = wl->window;
TAILQ_FOREACH(wp, &w->panes, entry) {
ft = format_create_defaults(NULL, c, s, wl, wp);
value = format_expand(ft, csub->format); value = format_expand(ft, csub->format);
format_free(ft);
find.pane = wp->id; find.pane = wp->id;
find.idx = wl->idx; find.idx = wl->idx;
@@ -946,18 +937,15 @@ control_check_subs_all_panes(struct client *c, struct control_sub *csub)
RB_INSERT(control_sub_panes, &csub->panes, csp); RB_INSERT(control_sub_panes, &csub->panes, csp);
} }
if (csp->last != NULL && if (csp->last != NULL && strcmp(value, csp->last) == 0) {
strcmp(value, csp->last) == 0) {
free(value); free(value);
continue; return;
} }
control_write(c, control_write(c,
"%%subscription-changed %s $%u @%u %u %%%u : %s", "%%subscription-changed %s $%u @%u %u %%%u : %s",
csub->name, s->id, w->id, wl->idx, wp->id, value); csub->name, s->id, w->id, wl->idx, wp->id, value);
free(csp->last); free(csp->last);
csp->last = value; csp->last = value;
}
}
} }
/* Check window subscription. */ /* Check window subscription. */
@@ -1006,23 +994,17 @@ control_check_subs_window(struct client *c, struct control_sub *csub)
} }
} }
/* Check all windows subscription. */ /* Check all-windows subscription for a window. */
static void static void
control_check_subs_all_windows(struct client *c, struct control_sub *csub) control_check_subs_all_windows_one(struct client *c, struct control_sub *csub,
struct format_tree *ft, struct winlink *wl)
{ {
struct session *s = c->session; struct session *s = c->session;
struct window *w; struct window *w = wl->window;
struct winlink *wl;
struct format_tree *ft;
char *value; char *value;
struct control_sub_window *csw, find; struct control_sub_window *csw, find;
RB_FOREACH(wl, winlinks, &s->windows) {
w = wl->window;
ft = format_create_defaults(NULL, c, s, wl, NULL);
value = format_expand(ft, csub->format); value = format_expand(ft, csub->format);
format_free(ft);
find.window = w->id; find.window = w->id;
find.idx = wl->idx; find.idx = wl->idx;
@@ -1037,14 +1019,13 @@ control_check_subs_all_windows(struct client *c, struct control_sub *csub)
if (csw->last != NULL && strcmp(value, csw->last) == 0) { if (csw->last != NULL && strcmp(value, csw->last) == 0) {
free(value); free(value);
continue; return;
} }
control_write(c, control_write(c,
"%%subscription-changed %s $%u @%u %u - : %s", "%%subscription-changed %s $%u @%u %u - : %s",
csub->name, s->id, w->id, wl->idx, value); csub->name, s->id, w->id, wl->idx, value);
free(csw->last); free(csw->last);
csw->last = value; csw->last = value;
}
} }
/* Check subscriptions timer. */ /* Check subscriptions timer. */
@@ -1054,30 +1035,91 @@ control_check_subs_timer(__unused int fd, __unused short events, void *data)
struct client *c = data; struct client *c = data;
struct control_state *cs = c->control_state; struct control_state *cs = c->control_state;
struct control_sub *csub, *csub1; struct control_sub *csub, *csub1;
struct session *s = c->session;
struct format_tree *ft;
struct winlink *wl;
struct window_pane *wp;
struct timeval tv = { .tv_sec = 1 }; struct timeval tv = { .tv_sec = 1 };
int have_session = 0, have_all_panes = 0;
int have_all_windows = 0;
log_debug("%s: timer fired", __func__); log_debug("%s: timer fired", __func__);
evtimer_add(&cs->subs_timer, &tv); evtimer_add(&cs->subs_timer, &tv);
RB_FOREACH_SAFE(csub, control_subs, &cs->subs, csub1) { /* Find which subscription types are present. */
RB_FOREACH(csub, control_subs, &cs->subs) {
switch (csub->type) { switch (csub->type) {
case CONTROL_SUB_SESSION: case CONTROL_SUB_SESSION:
control_check_subs_session(c, csub); have_session = 1;
break;
case CONTROL_SUB_PANE:
control_check_subs_pane(c, csub);
break; break;
case CONTROL_SUB_ALL_PANES: case CONTROL_SUB_ALL_PANES:
control_check_subs_all_panes(c, csub); have_all_panes = 1;
break;
case CONTROL_SUB_ALL_WINDOWS:
have_all_windows = 1;
break;
default:
break;
}
}
/* Check session subscriptions. */
if (have_session) {
ft = format_create_defaults(NULL, c, s, NULL, NULL);
RB_FOREACH_SAFE(csub, control_subs, &cs->subs, csub1) {
if (csub->type == CONTROL_SUB_SESSION)
control_check_subs_session(c, csub, ft);
}
format_free(ft);
}
/* Check pane and window subscriptions. */
RB_FOREACH_SAFE(csub, control_subs, &cs->subs, csub1) {
switch (csub->type) {
case CONTROL_SUB_PANE:
control_check_subs_pane(c, csub);
break; break;
case CONTROL_SUB_WINDOW: case CONTROL_SUB_WINDOW:
control_check_subs_window(c, csub); control_check_subs_window(c, csub);
break; break;
case CONTROL_SUB_SESSION:
case CONTROL_SUB_ALL_PANES:
case CONTROL_SUB_ALL_WINDOWS: case CONTROL_SUB_ALL_WINDOWS:
control_check_subs_all_windows(c, csub);
break; break;
} }
} }
/* Check all-panes subscriptions. */
if (have_all_panes) {
RB_FOREACH(wl, winlinks, &s->windows) {
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
ft = format_create_defaults(NULL, c, s, wl, wp);
RB_FOREACH_SAFE(csub, control_subs, &cs->subs,
csub1) {
if (csub->type != CONTROL_SUB_ALL_PANES)
continue;
control_check_subs_all_panes_one(c,
csub, ft, wl, wp);
}
format_free(ft);
}
}
}
/* Check all-windows subscriptions. */
if (have_all_windows) {
RB_FOREACH(wl, winlinks, &s->windows) {
ft = format_create_defaults(NULL, c, s, wl, NULL);
RB_FOREACH_SAFE(csub, control_subs, &cs->subs,
csub1) {
if (csub->type != CONTROL_SUB_ALL_WINDOWS)
continue;
control_check_subs_all_windows_one(c, csub, ft,
wl);
}
format_free(ft);
}
}
} }
/* Add a subscription. */ /* Add a subscription. */