Merge branch 'obsd-master'

This commit is contained in:
Thomas Adam
2018-08-23 19:02:40 +01:00
8 changed files with 141 additions and 97 deletions

View File

@ -132,14 +132,16 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
static void static void
cmd_if_shell_callback(struct job *job) cmd_if_shell_callback(struct job *job)
{ {
struct cmd_if_shell_data *cdata = job->data; struct cmd_if_shell_data *cdata = job_get_data(job);
struct client *c = cdata->client; struct client *c = cdata->client;
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
struct cmdq_item *new_item; struct cmdq_item *new_item;
char *cause, *cmd, *file = cdata->file; char *cause, *cmd, *file = cdata->file;
u_int line = cdata->line; u_int line = cdata->line;
int status;
if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0) status = job_get_status(job);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
cmd = cdata->cmd_else; cmd = cdata->cmd_else;
else else
cmd = cdata->cmd_if; cmd = cdata->cmd_if;

View File

@ -57,7 +57,7 @@ struct cmd_run_shell_data {
static void static void
cmd_run_shell_print(struct job *job, const char *msg) cmd_run_shell_print(struct job *job, const char *msg)
{ {
struct cmd_run_shell_data *cdata = job->data; struct cmd_run_shell_data *cdata = job_get_data(job);
struct window_pane *wp = NULL; struct window_pane *wp = NULL;
struct cmd_find_state fs; struct cmd_find_state fs;
@ -113,22 +113,23 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
static void static void
cmd_run_shell_callback(struct job *job) cmd_run_shell_callback(struct job *job)
{ {
struct cmd_run_shell_data *cdata = job->data; struct cmd_run_shell_data *cdata = job_get_data(job);
char *cmd = cdata->cmd, *msg, *line; struct bufferevent *event = job_get_event(job);
char *cmd = cdata->cmd, *msg = NULL, *line;
size_t size; size_t size;
int retcode; int retcode, status;
do { do {
if ((line = evbuffer_readline(job->event->input)) != NULL) { if ((line = evbuffer_readline(event->input)) != NULL) {
cmd_run_shell_print(job, line); cmd_run_shell_print(job, line);
free(line); free(line);
} }
} while (line != NULL); } while (line != NULL);
size = EVBUFFER_LENGTH(job->event->input); size = EVBUFFER_LENGTH(event->input);
if (size != 0) { if (size != 0) {
line = xmalloc(size + 1); line = xmalloc(size + 1);
memcpy(line, EVBUFFER_DATA(job->event->input), size); memcpy(line, EVBUFFER_DATA(event->input), size);
line[size] = '\0'; line[size] = '\0';
cmd_run_shell_print(job, line); cmd_run_shell_print(job, line);
@ -136,12 +137,12 @@ cmd_run_shell_callback(struct job *job)
free(line); free(line);
} }
msg = NULL; status = job_get_status(job);
if (WIFEXITED(job->status)) { if (WIFEXITED(status)) {
if ((retcode = WEXITSTATUS(job->status)) != 0) if ((retcode = WEXITSTATUS(status)) != 0)
xasprintf(&msg, "'%s' returned %d", cmd, retcode); xasprintf(&msg, "'%s' returned %d", cmd, retcode);
} else if (WIFSIGNALED(job->status)) { } else if (WIFSIGNALED(status)) {
retcode = WTERMSIG(job->status); retcode = WTERMSIG(status);
xasprintf(&msg, "'%s' terminated by signal %d", cmd, retcode); xasprintf(&msg, "'%s' terminated by signal %d", cmd, retcode);
} }
if (msg != NULL) if (msg != NULL)

View File

@ -43,7 +43,6 @@ const struct cmd_entry cmd_show_messages_entry = {
}; };
static int cmd_show_messages_terminals(struct cmdq_item *, int); static int cmd_show_messages_terminals(struct cmdq_item *, int);
static int cmd_show_messages_jobs(struct cmdq_item *, int);
static int static int
cmd_show_messages_terminals(struct cmdq_item *item, int blank) cmd_show_messages_terminals(struct cmdq_item *item, int blank)
@ -66,25 +65,6 @@ cmd_show_messages_terminals(struct cmdq_item *item, int blank)
return (n != 0); return (n != 0);
} }
static int
cmd_show_messages_jobs(struct cmdq_item *item, int blank)
{
struct job *job;
u_int n;
n = 0;
LIST_FOREACH(job, &all_jobs, entry) {
if (blank) {
cmdq_print(item, "%s", "");
blank = 0;
}
cmdq_print(item, "Job %u: %s [fd=%d, pid=%ld, status=%d]",
n, job->cmd, job->fd, (long)job->pid, job->status);
n++;
}
return (n != 0);
}
static enum cmd_retval static enum cmd_retval
cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item) cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item)
{ {
@ -103,7 +83,7 @@ cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item)
done = 1; done = 1;
} }
if (args_has(args, 'J')) { if (args_has(args, 'J')) {
cmd_show_messages_jobs(item, blank); job_print_summary(item, blank);
done = 1; done = 1;
} }
if (done) if (done)

View File

@ -191,8 +191,8 @@ static const char *format_lower[] = {
static void static void
format_job_update(struct job *job) format_job_update(struct job *job)
{ {
struct format_job *fj = job->data; struct format_job *fj = job_get_data(job);
struct evbuffer *evb = job->event->input; struct evbuffer *evb = job_get_event(job)->input;
char *line = NULL, *next; char *line = NULL, *next;
time_t t; time_t t;
@ -221,18 +221,19 @@ format_job_update(struct job *job)
static void static void
format_job_complete(struct job *job) format_job_complete(struct job *job)
{ {
struct format_job *fj = job->data; struct format_job *fj = job_get_data(job);
struct evbuffer *evb = job_get_event(job)->input;
char *line, *buf; char *line, *buf;
size_t len; size_t len;
fj->job = NULL; fj->job = NULL;
buf = NULL; buf = NULL;
if ((line = evbuffer_readline(job->event->input)) == NULL) { if ((line = evbuffer_readline(evb)) == NULL) {
len = EVBUFFER_LENGTH(job->event->input); len = EVBUFFER_LENGTH(evb);
buf = xmalloc(len + 1); buf = xmalloc(len + 1);
if (len != 0) if (len != 0)
memcpy(buf, EVBUFFER_DATA(job->event->input), len); memcpy(buf, EVBUFFER_DATA(evb), len);
buf[len] = '\0'; buf[len] = '\0';
} else } else
buf = line; buf = line;

100
job.c
View File

@ -36,8 +36,32 @@ static void job_read_callback(struct bufferevent *, void *);
static void job_write_callback(struct bufferevent *, void *); static void job_write_callback(struct bufferevent *, void *);
static void job_error_callback(struct bufferevent *, short, void *); static void job_error_callback(struct bufferevent *, short, void *);
struct job {
enum {
JOB_RUNNING,
JOB_DEAD,
JOB_CLOSED
} state;
int flags;
char *cmd;
pid_t pid;
int status;
int fd;
struct bufferevent *event;
job_update_cb updatecb;
job_complete_cb completecb;
job_free_cb freecb;
void *data;
LIST_ENTRY(job) entry;
};
/* All jobs list. */ /* All jobs list. */
struct joblist all_jobs = LIST_HEAD_INITIALIZER(all_jobs); LIST_HEAD(joblist, job) all_jobs = LIST_HEAD_INITIALIZER(all_jobs);
/* Start a job running, if it isn't already. */ /* Start a job running, if it isn't already. */
struct job * struct job *
@ -207,8 +231,16 @@ job_error_callback(__unused struct bufferevent *bufev, __unused short events,
/* Job died (waitpid() returned its pid). */ /* Job died (waitpid() returned its pid). */
void void
job_died(struct job *job, int status) job_check_died(pid_t pid, int status)
{ {
struct job *job;
LIST_FOREACH(job, &all_jobs, entry) {
if (pid == job->pid)
break;
}
if (job == NULL)
return;
log_debug("job died %p: %s, pid %ld", job, job->cmd, (long) job->pid); log_debug("job died %p: %s, pid %ld", job, job->cmd, (long) job->pid);
job->status = status; job->status = status;
@ -222,3 +254,67 @@ job_died(struct job *job, int status)
job->state = JOB_DEAD; job->state = JOB_DEAD;
} }
} }
/* Get job status. */
int
job_get_status(struct job *job)
{
return (job->status);
}
/* Get job data. */
void *
job_get_data(struct job *job)
{
return (job->data);
}
/* Get job event. */
struct bufferevent *
job_get_event(struct job *job)
{
return (job->event);
}
/* Kill all jobs. */
void
job_kill_all(void)
{
struct job *job;
LIST_FOREACH(job, &all_jobs, entry) {
if (job->pid != -1)
kill(job->pid, SIGTERM);
}
}
/* Are any jobs still running? */
int
job_still_running(void)
{
struct job *job;
LIST_FOREACH(job, &all_jobs, entry) {
if ((~job->flags & JOB_NOWAIT) && job->state == JOB_RUNNING)
return (1);
}
return (0);
}
/* Print job summary. */
void
job_print_summary(struct cmdq_item *item, int blank)
{
struct job *job;
u_int n = 0;
LIST_FOREACH(job, &all_jobs, entry) {
if (blank) {
cmdq_print(item, "%s", "");
blank = 0;
}
cmdq_print(item, "Job %u: %s [fd=%d, pid=%ld, status=%d]",
n, job->cmd, job->fd, (long)job->pid, job->status);
n++;
}
}

View File

@ -161,7 +161,6 @@ server_start(struct tmuxproc *client, struct event_base *base, int lockfd,
char *lockfile) char *lockfile)
{ {
int pair[2]; int pair[2];
struct job *job;
sigset_t set, oldset; sigset_t set, oldset;
struct client *c; struct client *c;
char *cause = NULL; char *cause = NULL;
@ -222,17 +221,13 @@ server_start(struct tmuxproc *client, struct event_base *base, int lockfd,
} }
start_cfg(); start_cfg();
server_add_accept(0); server_add_accept(0);
proc_loop(server_proc, server_loop); proc_loop(server_proc, server_loop);
LIST_FOREACH(job, &all_jobs, entry) { job_kill_all();
if (job->pid != -1)
kill(job->pid, SIGTERM);
}
status_prompt_save_history(); status_prompt_save_history();
exit(0); exit(0);
} }
@ -242,7 +237,6 @@ server_loop(void)
{ {
struct client *c; struct client *c;
u_int items; u_int items;
struct job *job;
do { do {
items = cmdq_next(NULL); items = cmdq_next(NULL);
@ -275,10 +269,8 @@ server_loop(void)
if (!TAILQ_EMPTY(&clients)) if (!TAILQ_EMPTY(&clients))
return (0); return (0);
LIST_FOREACH(job, &all_jobs, entry) { if (job_still_running())
if ((~job->flags & JOB_NOWAIT) && job->state == JOB_RUNNING)
return (0); return (0);
}
return (1); return (1);
} }
@ -456,7 +448,6 @@ server_child_exited(pid_t pid, int status)
{ {
struct window *w, *w1; struct window *w, *w1;
struct window_pane *wp; struct window_pane *wp;
struct job *job;
RB_FOREACH_SAFE(w, windows, &windows, w1) { RB_FOREACH_SAFE(w, windows, &windows, w1) {
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
@ -473,13 +464,7 @@ server_child_exited(pid_t pid, int status)
} }
} }
} }
job_check_died(pid, status);
LIST_FOREACH(job, &all_jobs, entry) {
if (pid == job->pid) {
job_died(job, status); /* might free job */
break;
}
}
} }
/* Handle stopped children. */ /* Handle stopped children. */

45
tmux.h
View File

@ -46,6 +46,7 @@ struct cmdq_list;
struct environ; struct environ;
struct format_job_tree; struct format_job_tree;
struct input_ctx; struct input_ctx;
struct job;
struct mode_tree_data; struct mode_tree_data;
struct mouse_event; struct mouse_event;
struct options; struct options;
@ -627,37 +628,6 @@ struct hook {
RB_ENTRY(hook) entry; RB_ENTRY(hook) entry;
}; };
/* Scheduled job. */
struct job;
typedef void (*job_update_cb) (struct job *);
typedef void (*job_complete_cb) (struct job *);
typedef void (*job_free_cb) (void *);
struct job {
enum {
JOB_RUNNING,
JOB_DEAD,
JOB_CLOSED
} state;
int flags;
#define JOB_NOWAIT 0x1
char *cmd;
pid_t pid;
int status;
int fd;
struct bufferevent *event;
job_update_cb updatecb;
job_complete_cb completecb;
job_free_cb freecb;
void *data;
LIST_ENTRY(job) entry;
};
LIST_HEAD(joblist, job);
/* Virtual screen. */ /* Virtual screen. */
struct screen_sel; struct screen_sel;
struct screen_titles; struct screen_titles;
@ -1659,11 +1629,20 @@ void options_style_update_old(struct options *,
extern const struct options_table_entry options_table[]; extern const struct options_table_entry options_table[];
/* job.c */ /* job.c */
extern struct joblist all_jobs; typedef void (*job_update_cb) (struct job *);
typedef void (*job_complete_cb) (struct job *);
typedef void (*job_free_cb) (void *);
#define JOB_NOWAIT 0x1
struct job *job_run(const char *, struct session *, const char *, struct job *job_run(const char *, struct session *, const char *,
job_update_cb, job_complete_cb, job_free_cb, void *, int); job_update_cb, job_complete_cb, job_free_cb, void *, int);
void job_free(struct job *); void job_free(struct job *);
void job_died(struct job *, int); void job_check_died(pid_t, int);
int job_get_status(struct job *);
void *job_get_data(struct job *);
struct bufferevent *job_get_event(struct job *);
void job_kill_all(void);
int job_still_running(void);
void job_print_summary(struct cmdq_item *, int);
/* environ.c */ /* environ.c */
struct environ *environ_create(void); struct environ *environ_create(void);

View File

@ -1687,7 +1687,7 @@ window_copy_copy_pipe(struct window_pane *wp, struct session *s,
expanded = format_single(NULL, arg, NULL, s, NULL, wp); expanded = format_single(NULL, arg, NULL, s, NULL, wp);
job = job_run(expanded, s, NULL, NULL, NULL, NULL, NULL, JOB_NOWAIT); job = job_run(expanded, s, NULL, NULL, NULL, NULL, NULL, JOB_NOWAIT);
bufferevent_write(job->event, buf, len); bufferevent_write(job_get_event(job), buf, len);
free(expanded); free(expanded);
window_copy_copy_buffer(wp, bufname, buf, len); window_copy_copy_buffer(wp, bufname, buf, len);