Move job struct into job.c.

This commit is contained in:
nicm 2018-08-23 15:45:05 +00:00
parent 55db3623bf
commit bceccc6b63
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
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 cmd_list *cmdlist;
struct cmdq_item *new_item;
char *cause, *cmd, *file = cdata->file;
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;
else
cmd = cdata->cmd_if;

View File

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

View File

@ -44,7 +44,6 @@ const struct cmd_entry cmd_show_messages_entry = {
};
static int cmd_show_messages_terminals(struct cmdq_item *, int);
static int cmd_show_messages_jobs(struct cmdq_item *, int);
static int
cmd_show_messages_terminals(struct cmdq_item *item, int blank)
@ -67,25 +66,6 @@ cmd_show_messages_terminals(struct cmdq_item *item, int blank)
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
cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item)
{
@ -104,7 +84,7 @@ cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item)
done = 1;
}
if (args_has(args, 'J')) {
cmd_show_messages_jobs(item, blank);
job_print_summary(item, blank);
done = 1;
}
if (done)

View File

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

100
job.c
View File

@ -37,8 +37,32 @@ static void job_read_callback(struct bufferevent *, void *);
static void job_write_callback(struct bufferevent *, 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. */
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. */
struct job *
@ -208,8 +232,16 @@ job_error_callback(__unused struct bufferevent *bufev, __unused short events,
/* Job died (waitpid() returned its pid). */
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);
job->status = status;
@ -223,3 +255,67 @@ job_died(struct job *job, int status)
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

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

45
tmux.h
View File

@ -44,6 +44,7 @@ struct cmdq_list;
struct environ;
struct format_job_tree;
struct input_ctx;
struct job;
struct mode_tree_data;
struct mouse_event;
struct options;
@ -619,37 +620,6 @@ struct hook {
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. */
struct screen_sel;
struct screen_titles;
@ -1628,11 +1598,20 @@ void options_style_update_old(struct options *,
extern const struct options_table_entry options_table[];
/* 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 *,
job_update_cb, job_complete_cb, job_free_cb, void *, int);
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 */
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);
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);
window_copy_copy_buffer(wp, bufname, buf, len);