summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd-if-shell.c6
-rw-r--r--cmd-run-shell.c4
-rw-r--r--cmd-server-info.c7
-rw-r--r--cmd-set-option.c36
-rw-r--r--job.c16
-rw-r--r--server-job.c5
-rw-r--r--status.c4
-rw-r--r--tmux.h4
8 files changed, 63 insertions, 19 deletions
diff --git a/cmd-if-shell.c b/cmd-if-shell.c
index e0775da8..82da814a 100644
--- a/cmd-if-shell.c
+++ b/cmd-if-shell.c
@@ -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) {
diff --git a/cmd-run-shell.c b/cmd-run-shell.c
index ca414dc8..1a8e28f4 100644
--- a/cmd-run-shell.c
+++ b/cmd-run-shell.c
@@ -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
diff --git a/cmd-server-info.c b/cmd-server-info.c
index b4cce636..4107527b 100644
--- a/cmd-server-info.c
+++ b/cmd-server-info.c
@@ -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);
}
diff --git a/cmd-set-option.c b/cmd-set-option.c
index a495a15d..536b623b 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -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);
}
}
diff --git a/job.c b/job.c
index 93ff0644..a638e3d8 100644
--- a/job.c
+++ b/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,15 +92,24 @@ 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);
SLIST_INSERT_HEAD(&all_jobs, job, lentry);
-
+
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)
diff --git a/server-job.c b/server-job.c
index 5a703b7b..6ff15860 100644
--- a/server-job.c
+++ b/server-job.c
@@ -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;
+ }
}
}
}
diff --git a/status.c b/status.c
index 9a3f4867..643c30c6 100644
--- a/status.c
+++ b/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)
diff --git a/tmux.h b/tmux.h
index 41ace3a8..73ac9803 100644
--- a/tmux.h
+++ b/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 *);