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:
Nicholas Marriott 2009-11-01 23:20:37 +00:00
parent 32299e4010
commit 2f813ef75d
8 changed files with 63 additions and 19 deletions

View File

@ -65,7 +65,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
if (ctx->curclient != NULL) if (ctx->curclient != NULL)
ctx->curclient->references++; 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); data->arg, cmd_if_shell_callback, cmd_if_shell_free, cdata);
job_run(job); job_run(job);
@ -80,10 +80,8 @@ cmd_if_shell_callback(struct job *job)
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
char *cause; char *cause;
if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0) { if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0)
job_free(job); /* calls cmd_if_shell_free */
return; return;
}
if (cmd_string_parse(cdata->cmd, &cmdlist, &cause) != 0) { if (cmd_string_parse(cdata->cmd, &cmdlist, &cause) != 0) {
if (cause != NULL) { if (cause != NULL) {

View File

@ -65,7 +65,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
if (ctx->curclient != NULL) if (ctx->curclient != NULL)
ctx->curclient->references++; 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); data->arg, cmd_run_shell_callback, cmd_run_shell_free, cdata);
job_run(job); job_run(job);
@ -117,8 +117,6 @@ cmd_run_shell_callback(struct job *job)
ctx->info(ctx, "%s", msg); ctx->info(ctx, "%s", msg);
xfree(msg); xfree(msg);
} }
job_free(job); /* calls cmd_run_shell_free */
} }
void void

View File

@ -56,6 +56,7 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
struct tty_code *code; struct tty_code *code;
struct tty_term_code_entry *ent; struct tty_term_code_entry *ent;
struct utsname un; struct utsname un;
struct job *job;
struct grid *gd; struct grid *gd;
struct grid_line *gl; struct grid_line *gl;
u_int i, j, k; 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, "%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); return (0);
} }

View File

@ -108,7 +108,10 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
struct client *c; struct client *c;
struct options *oo; struct options *oo;
const struct set_option_entry *entry, *opt; const struct set_option_entry *entry, *opt;
struct jobs *jobs;
struct job *job, *nextjob;
u_int i; u_int i;
int try_again;
if (data->chflags & CMD_CHFLAG('g')) if (data->chflags & CMD_CHFLAG('g'))
oo = &global_s_options; oo = &global_s_options;
@ -184,11 +187,34 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
recalculate_sizes(); recalculate_sizes();
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i); /*
if (c != NULL && c->session != NULL) { * Special-case: kill all persistent jobs if status-left, status-right
job_tree_free(&c->status_jobs); * or set-titles-string have changed. Persistent jobs are only used by
job_tree_init(&c->status_jobs); * 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); server_redraw_client(c);
} }
} }

16
job.c
View File

@ -73,7 +73,7 @@ job_get(struct jobs *jobs, const char *cmd)
/* Add a job. */ /* Add a job. */
struct 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) void (*callbackfn)(struct job *), void (*freefn)(void *), void *data)
{ {
struct job *job; struct job *job;
@ -81,6 +81,7 @@ job_add(struct jobs *jobs, struct client *c, const char *cmd,
job = xmalloc(sizeof *job); job = xmalloc(sizeof *job);
job->cmd = xstrdup(cmd); job->cmd = xstrdup(cmd);
job->pid = -1; job->pid = -1;
job->status = 0;
job->client = c; job->client = c;
@ -91,15 +92,24 @@ job_add(struct jobs *jobs, struct client *c, const char *cmd,
job->freefn = freefn; job->freefn = freefn;
job->data = data; job->data = data;
job->flags = JOB_DONE; job->flags = flags|JOB_DONE;
if (jobs != NULL) if (jobs != NULL)
RB_INSERT(jobs, jobs, job); RB_INSERT(jobs, jobs, job);
SLIST_INSERT_HEAD(&all_jobs, job, lentry); SLIST_INSERT_HEAD(&all_jobs, job, lentry);
return (job); 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. */ /* Kill and free an individual job. */
void void
job_free(struct job *job) job_free(struct job *job)

View File

@ -64,7 +64,10 @@ restart:
if (job->callbackfn != NULL) { if (job->callbackfn != NULL) {
job->callbackfn(job); job->callbackfn(job);
goto restart; /* could be freed by callback */ if ((!job->flags & JOB_PERSIST)) {
job_free(job);
goto restart;
}
} }
} }
} }

View File

@ -476,8 +476,8 @@ status_job(struct client *c, char **iptr)
job = job_get(&c->status_jobs, cmd); job = job_get(&c->status_jobs, cmd);
if (job == NULL) { if (job == NULL) {
job = job_add( job = job_add(&c->status_jobs,
&c->status_jobs, c, cmd, status_job_callback, xfree, NULL); JOB_PERSIST, c, cmd, status_job_callback, xfree, NULL);
job_run(job); job_run(job);
} }
if (job->data == NULL) if (job->data == NULL)

4
tmux.h
View File

@ -669,6 +669,7 @@ struct job {
int flags; int flags;
#define JOB_DONE 0x1 #define JOB_DONE 0x1
#define JOB_PERSIST 0x2 /* don't free after callback */
RB_ENTRY(job) entry; RB_ENTRY(job) entry;
SLIST_ENTRY(job) lentry; SLIST_ENTRY(job) lentry;
@ -1301,8 +1302,9 @@ RB_PROTOTYPE(jobs, job, entry, job_cmp);
void job_tree_init(struct jobs *); void job_tree_init(struct jobs *);
void job_tree_free(struct jobs *); void job_tree_free(struct jobs *);
struct job *job_get(struct jobs *, const char *); 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 *); const char *, void (*)(struct job *), void (*)(void *), void *);
void job_remove(struct jobs *, struct job *);
void job_free(struct job *); void job_free(struct job *);
int job_run(struct job *); int job_run(struct job *);
void job_kill(struct job *); void job_kill(struct job *);