version 1.42, 2017/03/09 17:02:38 |
version 1.43, 2017/04/20 09:20:22 |
|
|
* output. |
* output. |
*/ |
*/ |
|
|
static void job_callback(struct bufferevent *, short, void *); |
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 *); |
|
|
/* All jobs list. */ |
/* All jobs list. */ |
struct joblist all_jobs = LIST_HEAD_INITIALIZER(all_jobs); |
struct joblist 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 * |
job_run(const char *cmd, struct session *s, const char *cwd, |
job_run(const char *cmd, struct session *s, const char *cwd, |
void (*callbackfn)(struct job *), void (*freefn)(void *), void *data) |
job_update_cb updatecb, job_complete_cb completecb, job_free_cb freecb, |
|
void *data) |
{ |
{ |
struct job *job; |
struct job *job; |
struct environ *env; |
struct environ *env; |
|
|
job->pid = pid; |
job->pid = pid; |
job->status = 0; |
job->status = 0; |
|
|
LIST_INSERT_HEAD(&all_jobs, job, lentry); |
LIST_INSERT_HEAD(&all_jobs, job, entry); |
|
|
job->callbackfn = callbackfn; |
job->updatecb = updatecb; |
job->freefn = freefn; |
job->completecb = completecb; |
|
job->freecb = freecb; |
job->data = data; |
job->data = data; |
|
|
job->fd = out[0]; |
job->fd = out[0]; |
setblocking(job->fd, 0); |
setblocking(job->fd, 0); |
|
|
job->event = bufferevent_new(job->fd, NULL, job_write_callback, |
job->event = bufferevent_new(job->fd, job_read_callback, |
job_callback, job); |
job_write_callback, job_error_callback, job); |
bufferevent_enable(job->event, EV_READ|EV_WRITE); |
bufferevent_enable(job->event, EV_READ|EV_WRITE); |
|
|
log_debug("run job %p: %s, pid %ld", job, job->cmd, (long) job->pid); |
log_debug("run job %p: %s, pid %ld", job, job->cmd, (long) job->pid); |
|
|
{ |
{ |
log_debug("free job %p: %s", job, job->cmd); |
log_debug("free job %p: %s", job, job->cmd); |
|
|
LIST_REMOVE(job, lentry); |
LIST_REMOVE(job, entry); |
free(job->cmd); |
free(job->cmd); |
|
|
if (job->freefn != NULL && job->data != NULL) |
if (job->freecb != NULL && job->data != NULL) |
job->freefn(job->data); |
job->freecb(job->data); |
|
|
if (job->pid != -1) |
if (job->pid != -1) |
kill(job->pid, SIGTERM); |
kill(job->pid, SIGTERM); |
|
|
free(job); |
free(job); |
} |
} |
|
|
/* Called when output buffer falls below low watermark (default is 0). */ |
/* Job buffer read callback. */ |
static void |
static void |
|
job_read_callback(__unused struct bufferevent *bufev, void *data) |
|
{ |
|
struct job *job = data; |
|
|
|
if (job->updatecb != NULL) |
|
job->updatecb (job); |
|
} |
|
|
|
/* |
|
* Job buffer write callback. Fired when the buffer falls below watermark |
|
* (default is empty). If all the data has been written, disable the write |
|
* event. |
|
*/ |
|
static void |
job_write_callback(__unused struct bufferevent *bufev, void *data) |
job_write_callback(__unused struct bufferevent *bufev, void *data) |
{ |
{ |
struct job *job = data; |
struct job *job = data; |
|
|
|
|
/* Job buffer error callback. */ |
/* Job buffer error callback. */ |
static void |
static void |
job_callback(__unused struct bufferevent *bufev, __unused short events, |
job_error_callback(__unused struct bufferevent *bufev, __unused short events, |
void *data) |
void *data) |
{ |
{ |
struct job *job = data; |
struct job *job = data; |
|
|
log_debug("job error %p: %s, pid %ld", job, job->cmd, (long) job->pid); |
log_debug("job error %p: %s, pid %ld", job, job->cmd, (long) job->pid); |
|
|
if (job->state == JOB_DEAD) { |
if (job->state == JOB_DEAD) { |
if (job->callbackfn != NULL) |
if (job->completecb != NULL) |
job->callbackfn(job); |
job->completecb(job); |
job_free(job); |
job_free(job); |
} else { |
} else { |
bufferevent_disable(job->event, EV_READ); |
bufferevent_disable(job->event, EV_READ); |
|
|
job->status = status; |
job->status = status; |
|
|
if (job->state == JOB_CLOSED) { |
if (job->state == JOB_CLOSED) { |
if (job->callbackfn != NULL) |
if (job->completecb != NULL) |
job->callbackfn(job); |
job->completecb(job); |
job_free(job); |
job_free(job); |
} else { |
} else { |
job->pid = -1; |
job->pid = -1; |