mirror of
https://github.com/tmux/tmux.git
synced 2024-12-13 01:48:47 +00:00
Add a flag for jobs that shouldn't be freed after they've died and use it for
status jobs, then only kill those jobs when status-left, status-right or set-titles-string is changed. Fixes problems with changing options from inside #().
This commit is contained in:
parent
32299e4010
commit
2f813ef75d
@ -65,7 +65,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
if (ctx->curclient != NULL)
|
||||
ctx->curclient->references++;
|
||||
|
||||
job = job_add(NULL, NULL,
|
||||
job = job_add(NULL, 0, NULL,
|
||||
data->arg, cmd_if_shell_callback, cmd_if_shell_free, cdata);
|
||||
job_run(job);
|
||||
|
||||
@ -80,10 +80,8 @@ cmd_if_shell_callback(struct job *job)
|
||||
struct cmd_list *cmdlist;
|
||||
char *cause;
|
||||
|
||||
if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0) {
|
||||
job_free(job); /* calls cmd_if_shell_free */
|
||||
if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd_string_parse(cdata->cmd, &cmdlist, &cause) != 0) {
|
||||
if (cause != NULL) {
|
||||
|
@ -65,7 +65,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
if (ctx->curclient != NULL)
|
||||
ctx->curclient->references++;
|
||||
|
||||
job = job_add(NULL, NULL,
|
||||
job = job_add(NULL, 0, NULL,
|
||||
data->arg, cmd_run_shell_callback, cmd_run_shell_free, cdata);
|
||||
job_run(job);
|
||||
|
||||
@ -117,8 +117,6 @@ cmd_run_shell_callback(struct job *job)
|
||||
ctx->info(ctx, "%s", msg);
|
||||
xfree(msg);
|
||||
}
|
||||
|
||||
job_free(job); /* calls cmd_run_shell_free */
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -56,6 +56,7 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
|
||||
struct tty_code *code;
|
||||
struct tty_term_code_entry *ent;
|
||||
struct utsname un;
|
||||
struct job *job;
|
||||
struct grid *gd;
|
||||
struct grid_line *gl;
|
||||
u_int i, j, k;
|
||||
@ -178,5 +179,11 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
|
||||
}
|
||||
ctx->print(ctx, "%s", "");
|
||||
|
||||
ctx->print(ctx, "Jobs:");
|
||||
SLIST_FOREACH(job, &all_jobs, lentry) {
|
||||
ctx->print(ctx, "%s [fd=%d, pid=%d, status=%d, flags=0x%x]",
|
||||
job->cmd, job->fd, job->pid, job->status, job->flags);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -108,7 +108,10 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
struct client *c;
|
||||
struct options *oo;
|
||||
const struct set_option_entry *entry, *opt;
|
||||
struct jobs *jobs;
|
||||
struct job *job, *nextjob;
|
||||
u_int i;
|
||||
int try_again;
|
||||
|
||||
if (data->chflags & CMD_CHFLAG('g'))
|
||||
oo = &global_s_options;
|
||||
@ -184,11 +187,34 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
}
|
||||
|
||||
recalculate_sizes();
|
||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||
c = ARRAY_ITEM(&clients, i);
|
||||
if (c != NULL && c->session != NULL) {
|
||||
job_tree_free(&c->status_jobs);
|
||||
job_tree_init(&c->status_jobs);
|
||||
|
||||
/*
|
||||
* Special-case: kill all persistent jobs if status-left, status-right
|
||||
* or set-titles-string have changed. Persistent jobs are only used by
|
||||
* the status line at the moment so this works XXX.
|
||||
*/
|
||||
if (strcmp(entry->name, "status-left") == 0 ||
|
||||
strcmp(entry->name, "status-right") == 0 ||
|
||||
strcmp(entry->name, "set-titles-string") == 0) {
|
||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||
c = ARRAY_ITEM(&clients, i);
|
||||
if (c == NULL || c->session == NULL)
|
||||
continue;
|
||||
|
||||
jobs = &c->status_jobs;
|
||||
do {
|
||||
try_again = 0;
|
||||
job = RB_ROOT(jobs);
|
||||
while (job != NULL) {
|
||||
nextjob = RB_NEXT(jobs, jobs, job);
|
||||
if (job->flags & JOB_PERSIST) {
|
||||
job_remove(jobs, job);
|
||||
try_again = 1;
|
||||
break;
|
||||
}
|
||||
job = nextjob;
|
||||
}
|
||||
} while (try_again);
|
||||
server_redraw_client(c);
|
||||
}
|
||||
}
|
||||
|
14
job.c
14
job.c
@ -73,7 +73,7 @@ job_get(struct jobs *jobs, const char *cmd)
|
||||
|
||||
/* Add a job. */
|
||||
struct job *
|
||||
job_add(struct jobs *jobs, struct client *c, const char *cmd,
|
||||
job_add(struct jobs *jobs, int flags, struct client *c, const char *cmd,
|
||||
void (*callbackfn)(struct job *), void (*freefn)(void *), void *data)
|
||||
{
|
||||
struct job *job;
|
||||
@ -81,6 +81,7 @@ job_add(struct jobs *jobs, struct client *c, const char *cmd,
|
||||
job = xmalloc(sizeof *job);
|
||||
job->cmd = xstrdup(cmd);
|
||||
job->pid = -1;
|
||||
job->status = 0;
|
||||
|
||||
job->client = c;
|
||||
|
||||
@ -91,7 +92,7 @@ job_add(struct jobs *jobs, struct client *c, const char *cmd,
|
||||
job->freefn = freefn;
|
||||
job->data = data;
|
||||
|
||||
job->flags = JOB_DONE;
|
||||
job->flags = flags|JOB_DONE;
|
||||
|
||||
if (jobs != NULL)
|
||||
RB_INSERT(jobs, jobs, job);
|
||||
@ -100,6 +101,15 @@ job_add(struct jobs *jobs, struct client *c, const char *cmd,
|
||||
return (job);
|
||||
}
|
||||
|
||||
/* Remove job from tree and free. */
|
||||
void
|
||||
job_remove(struct jobs *jobs, struct job *job)
|
||||
{
|
||||
if (jobs != NULL)
|
||||
RB_REMOVE(jobs, jobs, job);
|
||||
job_free(job);
|
||||
}
|
||||
|
||||
/* Kill and free an individual job. */
|
||||
void
|
||||
job_free(struct job *job)
|
||||
|
@ -64,7 +64,10 @@ restart:
|
||||
|
||||
if (job->callbackfn != NULL) {
|
||||
job->callbackfn(job);
|
||||
goto restart; /* could be freed by callback */
|
||||
if ((!job->flags & JOB_PERSIST)) {
|
||||
job_free(job);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
4
status.c
4
status.c
@ -476,8 +476,8 @@ status_job(struct client *c, char **iptr)
|
||||
|
||||
job = job_get(&c->status_jobs, cmd);
|
||||
if (job == NULL) {
|
||||
job = job_add(
|
||||
&c->status_jobs, c, cmd, status_job_callback, xfree, NULL);
|
||||
job = job_add(&c->status_jobs,
|
||||
JOB_PERSIST, c, cmd, status_job_callback, xfree, NULL);
|
||||
job_run(job);
|
||||
}
|
||||
if (job->data == NULL)
|
||||
|
4
tmux.h
4
tmux.h
@ -669,6 +669,7 @@ struct job {
|
||||
|
||||
int flags;
|
||||
#define JOB_DONE 0x1
|
||||
#define JOB_PERSIST 0x2 /* don't free after callback */
|
||||
|
||||
RB_ENTRY(job) entry;
|
||||
SLIST_ENTRY(job) lentry;
|
||||
@ -1301,8 +1302,9 @@ RB_PROTOTYPE(jobs, job, entry, job_cmp);
|
||||
void job_tree_init(struct jobs *);
|
||||
void job_tree_free(struct jobs *);
|
||||
struct job *job_get(struct jobs *, const char *);
|
||||
struct job *job_add(struct jobs *, struct client *,
|
||||
struct job *job_add(struct jobs *, int, struct client *,
|
||||
const char *, void (*)(struct job *), void (*)(void *), void *);
|
||||
void job_remove(struct jobs *, struct job *);
|
||||
void job_free(struct job *);
|
||||
int job_run(struct job *);
|
||||
void job_kill(struct job *);
|
||||
|
Loading…
Reference in New Issue
Block a user