From: nicm Date: Mon, 1 May 2017 12:20:55 +0000 (+0000) Subject: In order that people can use formats like #D in #() in the status line X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=d559dd45c594cdabf93a350fe402dc4fa248c88f;p=openbsd In order that people can use formats like #D in #() in the status line and not have to wait for an update when they change pane, we allow commands to run more than once a second if the expanded form changes. Unfortunately this can mean them being run far too often (pretty much continually) when multiple clients exist, because some formats (including #D) will always differ between clients. To avoid this, give each client its own tree of jobs which means that the same command will be different instances for each client - similar to how we have the tag to separate commands for different panes. GitHub issue 889; test case reported by Paul Johnson. --- diff --git a/usr.bin/tmux/cfg.c b/usr.bin/tmux/cfg.c index b9f6ab06678..6257930b2f2 100644 --- a/usr.bin/tmux/cfg.c +++ b/usr.bin/tmux/cfg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cfg.c,v 1.58 2017/04/25 14:46:23 nicm Exp $ */ +/* $OpenBSD: cfg.c,v 1.59 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -148,7 +148,8 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int quiet) line); continue; } - ft = format_create(NULL, FORMAT_NONE, FORMAT_NOJOBS); + ft = format_create(NULL, NULL, FORMAT_NONE, + FORMAT_NOJOBS); s = p + 3; while (isspace((u_char)*s)) diff --git a/usr.bin/tmux/cmd-display-message.c b/usr.bin/tmux/cmd-display-message.c index afb3a4826c5..c4aa3226bbd 100644 --- a/usr.bin/tmux/cmd-display-message.c +++ b/usr.bin/tmux/cmd-display-message.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-display-message.c,v 1.41 2017/04/22 10:22:39 nicm Exp $ */ +/* $OpenBSD: cmd-display-message.c,v 1.42 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2009 Tiago Cunha @@ -73,7 +73,7 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item) if (template == NULL) template = DISPLAY_MESSAGE_TEMPLATE; - ft = format_create(item, FORMAT_NONE, 0); + ft = format_create(item->client, item, FORMAT_NONE, 0); format_defaults(ft, c, s, wl, wp); msg = format_expand_time(ft, template, time(NULL)); diff --git a/usr.bin/tmux/cmd-list-buffers.c b/usr.bin/tmux/cmd-list-buffers.c index 56efd29afae..95d109d4826 100644 --- a/usr.bin/tmux/cmd-list-buffers.c +++ b/usr.bin/tmux/cmd-list-buffers.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-list-buffers.c,v 1.34 2017/02/03 11:57:27 nicm Exp $ */ +/* $OpenBSD: cmd-list-buffers.c,v 1.35 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -57,7 +57,7 @@ cmd_list_buffers_exec(struct cmd *self, struct cmdq_item *item) pb = NULL; while ((pb = paste_walk(pb)) != NULL) { - ft = format_create(item, FORMAT_NONE, 0); + ft = format_create(item->client, item, FORMAT_NONE, 0); format_defaults_paste_buffer(ft, pb); line = format_expand(ft, template); diff --git a/usr.bin/tmux/cmd-list-clients.c b/usr.bin/tmux/cmd-list-clients.c index 3d489a05b1e..83b7fcb2d62 100644 --- a/usr.bin/tmux/cmd-list-clients.c +++ b/usr.bin/tmux/cmd-list-clients.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-list-clients.c,v 1.33 2017/04/22 10:22:39 nicm Exp $ */ +/* $OpenBSD: cmd-list-clients.c,v 1.34 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -72,7 +72,7 @@ cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item) if (c->session == NULL || (s != NULL && s != c->session)) continue; - ft = format_create(item, FORMAT_NONE, 0); + ft = format_create(item->client, item, FORMAT_NONE, 0); format_add(ft, "line", "%u", idx); format_defaults(ft, c, NULL, NULL, NULL); diff --git a/usr.bin/tmux/cmd-list-keys.c b/usr.bin/tmux/cmd-list-keys.c index aab3c77bf67..919571f15e8 100644 --- a/usr.bin/tmux/cmd-list-keys.c +++ b/usr.bin/tmux/cmd-list-keys.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-list-keys.c,v 1.43 2017/04/21 14:01:19 nicm Exp $ */ +/* $OpenBSD: cmd-list-keys.c,v 1.44 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -144,7 +144,7 @@ cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item) "#{command_list_usage}"; } - ft = format_create(item, FORMAT_NONE, 0); + ft = format_create(item->client, item, FORMAT_NONE, 0); format_defaults(ft, NULL, NULL, NULL, NULL); for (entryp = cmd_table; *entryp != NULL; entryp++) { diff --git a/usr.bin/tmux/cmd-list-panes.c b/usr.bin/tmux/cmd-list-panes.c index 1f81dee1a9f..6a9f99e6f77 100644 --- a/usr.bin/tmux/cmd-list-panes.c +++ b/usr.bin/tmux/cmd-list-panes.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-list-panes.c,v 1.32 2017/04/22 10:22:39 nicm Exp $ */ +/* $OpenBSD: cmd-list-panes.c,v 1.33 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -123,7 +123,7 @@ cmd_list_panes_window(struct cmd *self, struct session *s, struct winlink *wl, n = 0; TAILQ_FOREACH(wp, &wl->window->panes, entry) { - ft = format_create(item, FORMAT_NONE, 0); + ft = format_create(item->client, item, FORMAT_NONE, 0); format_add(ft, "line", "%u", n); format_defaults(ft, NULL, s, wl, wp); diff --git a/usr.bin/tmux/cmd-list-sessions.c b/usr.bin/tmux/cmd-list-sessions.c index 9e3bc6578df..dc5105972a9 100644 --- a/usr.bin/tmux/cmd-list-sessions.c +++ b/usr.bin/tmux/cmd-list-sessions.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-list-sessions.c,v 1.28 2017/02/03 11:57:27 nicm Exp $ */ +/* $OpenBSD: cmd-list-sessions.c,v 1.29 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -65,7 +65,7 @@ cmd_list_sessions_exec(struct cmd *self, struct cmdq_item *item) n = 0; RB_FOREACH(s, sessions, &sessions) { - ft = format_create(item, FORMAT_NONE, 0); + ft = format_create(item->client, item, FORMAT_NONE, 0); format_add(ft, "line", "%u", n); format_defaults(ft, NULL, s, NULL, NULL); diff --git a/usr.bin/tmux/cmd-list-windows.c b/usr.bin/tmux/cmd-list-windows.c index fa4572a6321..4eebbbc6a59 100644 --- a/usr.bin/tmux/cmd-list-windows.c +++ b/usr.bin/tmux/cmd-list-windows.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-list-windows.c,v 1.42 2017/04/22 10:22:39 nicm Exp $ */ +/* $OpenBSD: cmd-list-windows.c,v 1.43 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -86,7 +86,7 @@ cmd_list_windows_session(struct cmd *self, struct session *s, { struct args *args = self->args; struct winlink *wl; - u_int n; + u_int n; struct format_tree *ft; const char *template; char *line; @@ -105,7 +105,7 @@ cmd_list_windows_session(struct cmd *self, struct session *s, n = 0; RB_FOREACH(wl, winlinks, &s->windows) { - ft = format_create(item, FORMAT_NONE, 0); + ft = format_create(item->client, item, FORMAT_NONE, 0); format_add(ft, "line", "%u", n); format_defaults(ft, NULL, s, wl, NULL); diff --git a/usr.bin/tmux/cmd-pipe-pane.c b/usr.bin/tmux/cmd-pipe-pane.c index 7ed9284ccd2..1f0a7956e6d 100644 --- a/usr.bin/tmux/cmd-pipe-pane.c +++ b/usr.bin/tmux/cmd-pipe-pane.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-pipe-pane.c,v 1.41 2017/04/22 10:22:39 nicm Exp $ */ +/* $OpenBSD: cmd-pipe-pane.c,v 1.42 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -90,7 +90,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item) } /* Expand the command. */ - ft = format_create(item, FORMAT_NONE, 0); + ft = format_create(item->client, item, FORMAT_NONE, 0); format_defaults(ft, c, s, wl, wp); cmd = format_expand_time(ft, args->argv[0], time(NULL)); format_free(ft); diff --git a/usr.bin/tmux/cmd-queue.c b/usr.bin/tmux/cmd-queue.c index 0abda7b27d3..68109e5c275 100644 --- a/usr.bin/tmux/cmd-queue.c +++ b/usr.bin/tmux/cmd-queue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-queue.c,v 1.54 2017/04/22 10:22:39 nicm Exp $ */ +/* $OpenBSD: cmd-queue.c,v 1.55 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2013 Nicholas Marriott @@ -299,7 +299,7 @@ cmdq_format(struct cmdq_item *item, const char *key, const char *fmt, ...) va_end(ap); if (shared->formats == NULL) - shared->formats = format_create(NULL, FORMAT_NONE, 0); + shared->formats = format_create(NULL, NULL, FORMAT_NONE, 0); format_add(shared->formats, key, "%s", value); free(value); diff --git a/usr.bin/tmux/format.c b/usr.bin/tmux/format.c index f5bd2794942..8e06ede6706 100644 --- a/usr.bin/tmux/format.c +++ b/usr.bin/tmux/format.c @@ -1,4 +1,4 @@ -/* $OpenBSD: format.c,v 1.130 2017/04/21 14:01:19 nicm Exp $ */ +/* $OpenBSD: format.c,v 1.131 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott @@ -76,6 +76,7 @@ static void format_defaults_winlink(struct format_tree *, /* Entry in format job tree. */ struct format_job { + struct client *client; u_int tag; const char *cmd; const char *expanded; @@ -128,6 +129,7 @@ struct format_tree { struct session *s; struct window_pane *wp; + struct client *client; u_int tag; int flags; @@ -236,7 +238,6 @@ format_job_complete(struct job *job) struct format_job *fj = job->data; char *line, *buf; size_t len; - struct client *c; fj->job = NULL; @@ -258,8 +259,8 @@ format_job_complete(struct job *job) free(buf); if (fj->status) { - TAILQ_FOREACH(c, &clients, entry) - server_status_client(c); + if (fj->client != NULL) + server_status_client(fj->client); fj->status = 0; } } @@ -268,22 +269,33 @@ format_job_complete(struct job *job) static char * format_job_get(struct format_tree *ft, const char *cmd) { + struct format_job_tree *jobs; struct format_job fj0, *fj; time_t t; char *expanded; int force; + if (ft->client == NULL) + jobs = &format_jobs; + else if (ft->client->jobs != NULL) + jobs = ft->client->jobs; + else { + jobs = ft->client->jobs = xmalloc(sizeof *ft->client->jobs); + RB_INIT(jobs); + } + fj0.tag = ft->tag; fj0.cmd = cmd; - if ((fj = RB_FIND(format_job_tree, &format_jobs, &fj0)) == NULL) { + if ((fj = RB_FIND(format_job_tree, jobs, &fj0)) == NULL) { fj = xcalloc(1, sizeof *fj); + fj->client = ft->client; fj->tag = ft->tag; fj->cmd = xstrdup(cmd); fj->expanded = NULL; xasprintf(&fj->out, "<'%s' not ready>", fj->cmd); - RB_INSERT(format_job_tree, &format_jobs, fj); + RB_INSERT(format_job_tree, jobs, fj); } expanded = format_expand(ft, cmd); @@ -314,17 +326,16 @@ format_job_get(struct format_tree *ft, const char *cmd) /* Remove old jobs. */ static void -format_job_timer(__unused int fd, __unused short events, __unused void *arg) +format_job_tidy(struct format_job_tree *jobs, int force) { struct format_job *fj, *fj1; time_t now; - struct timeval tv = { .tv_sec = 60 }; now = time(NULL); - RB_FOREACH_SAFE(fj, format_job_tree, &format_jobs, fj1) { - if (fj->last > now || now - fj->last < 3600) + RB_FOREACH_SAFE(fj, format_job_tree, jobs, fj1) { + if (!force && (fj->last > now || now - fj->last < 3600)) continue; - RB_REMOVE(format_job_tree, &format_jobs, fj); + RB_REMOVE(format_job_tree, jobs, fj); log_debug("%s: %s", __func__, fj->cmd); @@ -337,6 +348,29 @@ format_job_timer(__unused int fd, __unused short events, __unused void *arg) free(fj); } +} + +/* Remove old jobs for client. */ +void +format_lost_client(struct client *c) +{ + if (c->jobs != NULL) + format_job_tidy(c->jobs, 1); + free(c->jobs); +} + +/* Remove old jobs periodically. */ +static void +format_job_timer(__unused int fd, __unused short events, __unused void *arg) +{ + struct client *c; + struct timeval tv = { .tv_sec = 60 }; + + format_job_tidy(&format_jobs, 0); + TAILQ_FOREACH(c, &clients, entry) { + if (c->jobs != NULL) + format_job_tidy(c->jobs, 0); + } evtimer_del(&format_job_event); evtimer_add(&format_job_event, &tv); @@ -533,7 +567,7 @@ format_merge(struct format_tree *ft, struct format_tree *from) /* Create a new tree. */ struct format_tree * -format_create(struct cmdq_item *item, int tag, int flags) +format_create(struct client *c, struct cmdq_item *item, int tag, int flags) { struct format_tree *ft; @@ -545,6 +579,11 @@ format_create(struct cmdq_item *item, int tag, int flags) ft = xcalloc(1, sizeof *ft); RB_INIT(&ft->tree); + if (c != NULL) { + ft->client = c; + ft->client->references++; + } + ft->tag = tag; ft->flags = flags; @@ -577,6 +616,8 @@ format_free(struct format_tree *ft) free(fe); } + if (ft->client != NULL) + server_client_unref(ft->client); free(ft); } @@ -1099,7 +1140,10 @@ format_single(struct cmdq_item *item, const char *fmt, struct client *c, struct format_tree *ft; char *expanded; - ft = format_create(item, FORMAT_NONE, 0); + if (item != NULL) + ft = format_create(item->client, item, FORMAT_NONE, 0); + else + ft = format_create(NULL, item, FORMAT_NONE, 0); format_defaults(ft, c, s, wl, wp); expanded = format_expand(ft, fmt); diff --git a/usr.bin/tmux/names.c b/usr.bin/tmux/names.c index 7d446b6ea04..9fa8d0c9ac8 100644 --- a/usr.bin/tmux/names.c +++ b/usr.bin/tmux/names.c @@ -1,4 +1,4 @@ -/* $OpenBSD: names.c,v 1.39 2017/02/03 11:57:27 nicm Exp $ */ +/* $OpenBSD: names.c,v 1.40 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -124,7 +124,7 @@ format_window_name(struct window *w) const char *fmt; char *name; - ft = format_create(NULL, FORMAT_WINDOW|w->id, 0); + ft = format_create(NULL, NULL, FORMAT_WINDOW|w->id, 0); format_defaults_window(ft, w); format_defaults_pane(ft, w->active); diff --git a/usr.bin/tmux/screen-redraw.c b/usr.bin/tmux/screen-redraw.c index a86e0433ff0..6af19b83b05 100644 --- a/usr.bin/tmux/screen-redraw.c +++ b/usr.bin/tmux/screen-redraw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: screen-redraw.c,v 1.45 2017/04/05 10:49:46 nicm Exp $ */ +/* $OpenBSD: screen-redraw.c,v 1.46 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -280,7 +280,7 @@ screen_redraw_make_pane_status(struct client *c, struct window *w, fmt = options_get_string(w->options, "pane-border-format"); - ft = format_create(NULL, FORMAT_PANE|wp->id, 0); + ft = format_create(c, NULL, FORMAT_PANE|wp->id, 0); format_defaults(ft, c, NULL, NULL, wp); memcpy(&old, &wp->status_screen, sizeof old); diff --git a/usr.bin/tmux/server-client.c b/usr.bin/tmux/server-client.c index d16b15a01a1..ce9956db60d 100644 --- a/usr.bin/tmux/server-client.c +++ b/usr.bin/tmux/server-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server-client.c,v 1.227 2017/04/22 08:56:24 nicm Exp $ */ +/* $OpenBSD: server-client.c,v 1.228 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -283,6 +283,7 @@ server_client_lost(struct client *c) free(c->prompt_string); free(c->prompt_buffer); + format_lost_client(c); environ_free(c->environ); proc_remove_peer(c->peer); @@ -1326,7 +1327,7 @@ server_client_set_title(struct client *c) template = options_get_string(s->options, "set-titles-string"); - ft = format_create(NULL, FORMAT_NONE, 0); + ft = format_create(c, NULL, FORMAT_NONE, 0); format_defaults(ft, c, NULL, NULL, NULL); title = format_expand_time(ft, template, time(NULL)); diff --git a/usr.bin/tmux/status.c b/usr.bin/tmux/status.c index d1d4bab061f..c82f69c8de7 100644 --- a/usr.bin/tmux/status.c +++ b/usr.bin/tmux/status.c @@ -1,4 +1,4 @@ -/* $OpenBSD: status.c,v 1.163 2017/04/22 12:55:06 nicm Exp $ */ +/* $OpenBSD: status.c,v 1.164 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -519,9 +519,9 @@ status_replace(struct client *c, struct winlink *wl, const char *fmt, time_t t) else tag = FORMAT_NONE; if (c->flags & CLIENT_STATUSFORCE) - ft = format_create(NULL, tag, FORMAT_STATUS|FORMAT_FORCE); + ft = format_create(c, NULL, tag, FORMAT_STATUS|FORMAT_FORCE); else - ft = format_create(NULL, tag, FORMAT_STATUS); + ft = format_create(c, NULL, tag, FORMAT_STATUS); format_defaults(ft, c, NULL, wl, NULL); expanded = format_expand_time(ft, fmt, t); @@ -663,7 +663,7 @@ status_prompt_set(struct client *c, const char *msg, const char *input, time_t t; char *tmp; - ft = format_create(NULL, FORMAT_NONE, 0); + ft = format_create(c, NULL, FORMAT_NONE, 0); format_defaults(ft, c, NULL, NULL, NULL); t = time(NULL); @@ -724,7 +724,7 @@ status_prompt_update(struct client *c, const char *msg, const char *input) time_t t; char *tmp; - ft = format_create(NULL, FORMAT_NONE, 0); + ft = format_create(c, NULL, FORMAT_NONE, 0); format_defaults(ft, c, NULL, NULL, NULL); t = time(NULL); diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index d5aef5774cf..fa09693f82b 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.755 2017/04/28 19:13:55 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.756 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -43,6 +43,7 @@ struct client; struct cmdq_item; struct cmdq_list; struct environ; +struct format_job_tree; struct input_ctx; struct mode_key_cmdstr; struct mouse_event; @@ -1290,6 +1291,7 @@ struct client { struct timeval activity_time; struct environ *environ; + struct format_job_tree *jobs; char *title; const char *cwd; @@ -1501,7 +1503,8 @@ char *paste_make_sample(struct paste_buffer *); #define FORMAT_PANE 0x80000000U #define FORMAT_WINDOW 0x40000000U struct format_tree; -struct format_tree *format_create(struct cmdq_item *, int, int); +struct format_tree *format_create(struct client *, struct cmdq_item *, int, + int); void format_free(struct format_tree *); void printflike(3, 4) format_add(struct format_tree *, const char *, const char *, ...); @@ -1517,6 +1520,7 @@ void format_defaults_pane(struct format_tree *, struct window_pane *); void format_defaults_paste_buffer(struct format_tree *, struct paste_buffer *); +void format_lost_client(struct client *); /* hooks.c */ struct hook; diff --git a/usr.bin/tmux/window-choose.c b/usr.bin/tmux/window-choose.c index f157ccf30e7..80b3de3a208 100644 --- a/usr.bin/tmux/window-choose.c +++ b/usr.bin/tmux/window-choose.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window-choose.c,v 1.89 2017/04/28 19:13:55 nicm Exp $ */ +/* $OpenBSD: window-choose.c,v 1.90 2017/05/01 12:20:55 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -202,7 +202,7 @@ window_choose_data_create(int type, struct client *c, struct session *s) wcd = xmalloc(sizeof *wcd); wcd->type = type; - wcd->ft = format_create(NULL, FORMAT_NONE, 0); + wcd->ft = format_create(c, NULL, FORMAT_NONE, 0); wcd->ft_template = NULL; wcd->command = NULL;