Thanks. Does this work though? Where do you enable the bufferevent for writes?
Or does libevent do that for us, I forget and no time to check... On Tue, Mar 19, 2013 at 01:53:39PM -0500, Chris Johnsen wrote: > On Tue, Mar 19, 2013 at 4:29 AM, Nicholas Marriott > <nicholas.marri...@gmail.com> wrote: > > Did you forget to attach the code? > > Sort of. I thought someone might have some comment on the general > idea or the brief outline of the changes (e.g. if anyone had already > explored related ideas). But I did end up with the lingering feeling > that I should have sent the code, too. > > The changes I made are below, all in one batch. > > I also have them in separate chunks (in Git, with more details about > the individual changes) like this: > > eafaa15 Remove unused out and outdone from struct job > 2ffa3f2 Pass session to job_run, if available > 898f154 Allow writing to job > 4485207 Use a writable job in copy-pipe > > -->8-- > > cmd-if-shell.c | 2 +- > cmd-run-shell.c | 2 +- > job.c | 32 +++++++++++++++++++++++++------- > status.c | 2 +- > tmux.h | 7 ++----- > window-copy.c | 22 +++++++++++----------- > 6 files changed, 41 insertions(+), 26 deletions(-) > > diff --git a/cmd-if-shell.c b/cmd-if-shell.c > index b22e326..dddd5d4 100644 > --- a/cmd-if-shell.c > +++ b/cmd-if-shell.c > @@ -89,7 +89,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq) > cdata->cmdq = cmdq; > cmdq->references++; > > - job_run(shellcmd, cmd_if_shell_callback, cmd_if_shell_free, cdata); > + job_run(shellcmd, s, cmd_if_shell_callback, cmd_if_shell_free, cdata); > free(shellcmd); > > if (cdata->bflag) > diff --git a/cmd-run-shell.c b/cmd-run-shell.c > index b163542..4df21ff 100644 > --- a/cmd-run-shell.c > +++ b/cmd-run-shell.c > @@ -103,7 +103,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq) > cdata->cmdq = cmdq; > cmdq->references++; > > - job_run(shellcmd, cmd_run_shell_callback, cmd_run_shell_free, cdata); > + job_run(shellcmd, s, cmd_run_shell_callback, cmd_run_shell_free, cdata); > > if (cdata->bflag) > return (CMD_RETURN_NORMAL); > diff --git a/job.c b/job.c > index 8885899..feb30c9 100644 > --- a/job.c > +++ b/job.c > @@ -32,13 +32,14 @@ > */ > > void job_callback(struct bufferevent *, short, void *); > +void job_write_callback(struct bufferevent *, void *); > > /* All jobs list. */ > struct joblist all_jobs = LIST_HEAD_INITIALIZER(all_jobs); > > /* Start a job running, if it isn't already. */ > struct job * > -job_run(const char *cmd, > +job_run(const char *cmd, struct session *s, > void (*callbackfn)(struct job *), void (*freefn)(void *), void *data) > { > struct job *job; > @@ -51,7 +52,9 @@ job_run(const char *cmd, > > environ_init(&env); > environ_copy(&global_environ, &env); > - server_fill_environ(NULL, &env); > + if (s != NULL) > + environ_copy(&s->environ, &env); > + server_fill_environ(s, &env); > > switch (pid = fork()) { > case -1: > @@ -63,20 +66,20 @@ job_run(const char *cmd, > environ_push(&env); > environ_free(&env); > > + if (dup2(out[1], STDIN_FILENO) == -1) > + fatal("dup2 failed"); > if (dup2(out[1], STDOUT_FILENO) == -1) > fatal("dup2 failed"); > - if (out[1] != STDOUT_FILENO) > + if (out[1] != STDIN_FILENO && out[1] != STDOUT_FILENO) > close(out[1]); > close(out[0]); > > nullfd = open(_PATH_DEVNULL, O_RDWR, 0); > if (nullfd < 0) > fatal("open failed"); > - if (dup2(nullfd, STDIN_FILENO) == -1) > - fatal("dup2 failed"); > if (dup2(nullfd, STDERR_FILENO) == -1) > fatal("dup2 failed"); > - if (nullfd != STDIN_FILENO && nullfd != STDERR_FILENO) > + if (nullfd != STDERR_FILENO) > close(nullfd); > > closefrom(STDERR_FILENO + 1); > @@ -103,7 +106,7 @@ job_run(const char *cmd, > job->fd = out[0]; > setblocking(job->fd, 0); > > - job->event = bufferevent_new(job->fd, NULL, NULL, job_callback, job); > + job->event = bufferevent_new(job->fd, NULL, job_write_callback, > job_callback, job); > bufferevent_enable(job->event, EV_READ); > > log_debug("run job %p: %s, pid %ld", job, job->cmd, (long) job->pid); > @@ -132,6 +135,21 @@ job_free(struct job *job) > free(job); > } > > +/* Called when output buffer falls below low watermark (default is 0) */ > +void > +job_write_callback(unused struct bufferevent *bufev, void *data) > +{ > + struct job *job = data; > + size_t len = EVBUFFER_LENGTH(EVBUFFER_OUTPUT(job->event)); > + > + log_debug("job write %p: %s, pid %ld, output left %lu", job, job->cmd, > + (long) job->pid, (unsigned long) len); > + if (len == 0) { > + shutdown(job->fd, SHUT_WR); > + bufferevent_disable(job->event, EV_WRITE); > + } > +} > + > /* Job buffer error callback. */ > void > job_callback(unused struct bufferevent *bufev, unused short events, void > *data) > diff --git a/status.c b/status.c > index 9166ea5..f120c38 100644 > --- a/status.c > +++ b/status.c > @@ -594,7 +594,7 @@ status_find_job(struct client *c, char **iptr) > > /* If not found at all, start the job and add to the tree. */ > if (so == NULL) { > - job_run(cmd, status_job_callback, status_job_free, c); > + job_run(cmd, NULL, status_job_callback, status_job_free, c); > c->references++; > > so = xmalloc(sizeof *so); > diff --git a/tmux.h b/tmux.h > index 7c4c55b..834ac6e 100644 > --- a/tmux.h > +++ b/tmux.h > @@ -776,9 +776,6 @@ struct job { > int fd; > struct bufferevent *event; > > - struct bufferevent *out; > - int outdone; > - > void (*callbackfn)(struct job *); > void (*freefn)(void *); > void *data; > @@ -1610,8 +1607,8 @@ int options_table_find(const char *, const struct > options_table_entry **, > > /* job.c */ > extern struct joblist all_jobs; > -struct job *job_run( > - const char *, void (*)(struct job *), void (*)(void *), void *); > +struct job *job_run(const char *, struct session *, > + void (*)(struct job *), void (*)(void *), void *); > void job_free(struct job *); > void job_died(struct job *, int); > > diff --git a/window-copy.c b/window-copy.c > index 2228b38..2dd65eb 100644 > --- a/window-copy.c > +++ b/window-copy.c > @@ -54,7 +54,8 @@ void window_copy_start_selection(struct window_pane > *); > int window_copy_update_selection(struct window_pane *); > void *window_copy_get_selection(struct window_pane *, size_t *); > void window_copy_copy_buffer(struct window_pane *, int, void *, size_t); > -void window_copy_copy_pipe(struct window_pane *, int, const char *); > +void window_copy_copy_pipe( > + struct window_pane *, struct session *, int, const char *); > void window_copy_copy_selection(struct window_pane *, int); > void window_copy_clear_selection(struct window_pane *); > void window_copy_copy_line( > @@ -539,7 +540,7 @@ window_copy_key(struct window_pane *wp, struct session > *sess, int key) > break; > case MODEKEYCOPY_COPYPIPE: > if (sess != NULL) { > - window_copy_copy_pipe(wp, data->numprefix, arg); > + window_copy_copy_pipe(wp, sess, data->numprefix, arg); > window_pane_reset_mode(wp); > return; > } > @@ -1397,21 +1398,20 @@ window_copy_copy_buffer(struct window_pane *wp, int > idx, void *buf, size_t len) > } > > void > -window_copy_copy_pipe(struct window_pane *wp, int idx, const char *arg) > +window_copy_copy_pipe( > + struct window_pane *wp, struct session *sess, int idx, const char *arg) > { > - void* buf; > - size_t len; > - FILE* f; > + void *buf; > + size_t len; > + struct job *job; > + > > buf = window_copy_get_selection(wp, &len); > if (buf == NULL) > return; > > - f = popen(arg, "w"); > - if (f != NULL) { > - fwrite(buf, 1, len, f); > - pclose(f); > - } > + job = job_run(arg, sess, NULL, NULL, NULL); > + bufferevent_write(job->event, buf, len); > > window_copy_copy_buffer(wp, idx, buf, len); > } > -- > 1.8.1.3 > > > ------------------------------------------------------------------------------ > Everyone hates slow websites. So do we. > Make your web apps faster with AppDynamics > Download AppDynamics Lite for free today: > http://p.sf.net/sfu/appdyn_d2d_mar > _______________________________________________ > tmux-users mailing list > tmux-users@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/tmux-users ------------------------------------------------------------------------------ Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_mar _______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users