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

Reply via email to