diff options
| author | Björn Linse <bjorn.linse@gmail.com> | 2017-11-26 10:18:01 +0100 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-11-26 10:18:01 +0100 | 
| commit | 207b7ca4bc16d52641eaa5244eef25a0dba91dbc (patch) | |
| tree | a3422eceb6eeaa692a7baf7171dfa5fd81ad86b2 /src/nvim/event/process.c | |
| parent | b57d9a4ff08fc1ef8db79d422b441b792493ff4e (diff) | |
| parent | 0de019b6a65c6dd5141b7e002343df3689065ce7 (diff) | |
| download | rneovim-207b7ca4bc16d52641eaa5244eef25a0dba91dbc.tar.gz rneovim-207b7ca4bc16d52641eaa5244eef25a0dba91dbc.tar.bz2 rneovim-207b7ca4bc16d52641eaa5244eef25a0dba91dbc.zip  | |
Merge pull request #6844 from bfredl/channel
channels: support buffered output and bytes sockets/stdio
Diffstat (limited to 'src/nvim/event/process.c')
| -rw-r--r-- | src/nvim/event/process.c | 123 | 
1 files changed, 53 insertions, 70 deletions
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index 41e793500a..4eb2dd0baf 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -25,28 +25,28 @@  // For pty processes SIGTERM is sent first (in case SIGHUP was not enough).  #define KILL_TIMEOUT_MS 2000 -#define CLOSE_PROC_STREAM(proc, stream) \ -  do { \ -    if (proc->stream && !proc->stream->closed) { \ -      stream_close(proc->stream, NULL, NULL); \ -    } \ -  } while (0) -  static bool process_is_tearing_down = false;  /// @returns zero on success, or negative error code -int process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL +int process_spawn(Process *proc, bool in, bool out, bool err) +  FUNC_ATTR_NONNULL_ALL  { -  if (proc->in) { -    uv_pipe_init(&proc->loop->uv, &proc->in->uv.pipe, 0); +  if (in) { +    uv_pipe_init(&proc->loop->uv, &proc->in.uv.pipe, 0); +  } else { +    proc->in.closed = true;    } -  if (proc->out) { -    uv_pipe_init(&proc->loop->uv, &proc->out->uv.pipe, 0); +  if (out) { +    uv_pipe_init(&proc->loop->uv, &proc->out.uv.pipe, 0); +  } else { +    proc->out.closed = true;    } -  if (proc->err) { -    uv_pipe_init(&proc->loop->uv, &proc->err->uv.pipe, 0); +  if (err) { +    uv_pipe_init(&proc->loop->uv, &proc->err.uv.pipe, 0); +  } else { +    proc->err.closed = true;    }    int status; @@ -62,14 +62,14 @@ int process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL    }    if (status) { -    if (proc->in) { -      uv_close((uv_handle_t *)&proc->in->uv.pipe, NULL); +    if (in) { +      uv_close((uv_handle_t *)&proc->in.uv.pipe, NULL);      } -    if (proc->out) { -      uv_close((uv_handle_t *)&proc->out->uv.pipe, NULL); +    if (out) { +      uv_close((uv_handle_t *)&proc->out.uv.pipe, NULL);      } -    if (proc->err) { -      uv_close((uv_handle_t *)&proc->err->uv.pipe, NULL); +    if (err) { +      uv_close((uv_handle_t *)&proc->err.uv.pipe, NULL);      }      if (proc->type == kProcessTypeUv) { @@ -82,30 +82,27 @@ int process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL      return status;    } -  if (proc->in) { -    stream_init(NULL, proc->in, -1, -                STRUCT_CAST(uv_stream_t, &proc->in->uv.pipe)); -    proc->in->events = proc->events; -    proc->in->internal_data = proc; -    proc->in->internal_close_cb = on_process_stream_close; +  if (in) { +    stream_init(NULL, &proc->in, -1, +                STRUCT_CAST(uv_stream_t, &proc->in.uv.pipe)); +    proc->in.internal_data = proc; +    proc->in.internal_close_cb = on_process_stream_close;      proc->refcount++;    } -  if (proc->out) { -    stream_init(NULL, proc->out, -1, -                STRUCT_CAST(uv_stream_t, &proc->out->uv.pipe)); -    proc->out->events = proc->events; -    proc->out->internal_data = proc; -    proc->out->internal_close_cb = on_process_stream_close; +  if (out) { +    stream_init(NULL, &proc->out, -1, +                STRUCT_CAST(uv_stream_t, &proc->out.uv.pipe)); +    proc->out.internal_data = proc; +    proc->out.internal_close_cb = on_process_stream_close;      proc->refcount++;    } -  if (proc->err) { -    stream_init(NULL, proc->err, -1, -                STRUCT_CAST(uv_stream_t, &proc->err->uv.pipe)); -    proc->err->events = proc->events; -    proc->err->internal_data = proc; -    proc->err->internal_close_cb = on_process_stream_close; +  if (err) { +    stream_init(NULL, &proc->err, -1, +                STRUCT_CAST(uv_stream_t, &proc->err.uv.pipe)); +    proc->err.internal_data = proc; +    proc->err.internal_close_cb = on_process_stream_close;      proc->refcount++;    } @@ -136,27 +133,11 @@ void process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL    pty_process_teardown(loop);  } -// Wrappers around `stream_close` that protect against double-closing.  void process_close_streams(Process *proc) FUNC_ATTR_NONNULL_ALL  { -  process_close_in(proc); -  process_close_out(proc); -  process_close_err(proc); -} - -void process_close_in(Process *proc) FUNC_ATTR_NONNULL_ALL -{ -  CLOSE_PROC_STREAM(proc, in); -} - -void process_close_out(Process *proc) FUNC_ATTR_NONNULL_ALL -{ -  CLOSE_PROC_STREAM(proc, out); -} - -void process_close_err(Process *proc) FUNC_ATTR_NONNULL_ALL -{ -  CLOSE_PROC_STREAM(proc, err); +  stream_may_close(&proc->in); +  stream_may_close(&proc->out); +  stream_may_close(&proc->err);  }  /// Synchronously wait for a process to finish @@ -164,16 +145,15 @@ void process_close_err(Process *proc) FUNC_ATTR_NONNULL_ALL  /// @param process  Process instance  /// @param ms       Time in milliseconds to wait for the process.  ///                 0 for no wait. -1 to wait until the process quits. -/// @return Exit code of the process. +/// @return Exit code of the process. proc->status will have the same value.  ///         -1 if the timeout expired while the process is still running.  ///         -2 if the user interruped the wait.  int process_wait(Process *proc, int ms, MultiQueue *events)    FUNC_ATTR_NONNULL_ARG(1)  { -  int status = -1;  // default    bool interrupted = false;    if (!proc->refcount) { -    status = proc->status; +    int status = proc->status;      LOOP_PROCESS_EVENTS(proc->loop, proc->events, 0);      return status;    } @@ -209,7 +189,9 @@ int process_wait(Process *proc, int ms, MultiQueue *events)    if (proc->refcount == 1) {      // Job exited, collect status and manually invoke close_cb to free the job      // resources -    status = interrupted ? -2 : proc->status; +    if (interrupted) { +      proc->status = -2; +    }      decref(proc);      if (events) {        // the decref call created an exit event, process it now @@ -219,7 +201,7 @@ int process_wait(Process *proc, int ms, MultiQueue *events)      proc->refcount--;    } -  return status; +  return proc->status;  }  /// Ask a process to terminate and eventually kill if it doesn't respond @@ -233,8 +215,9 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL    switch (proc->type) {      case kProcessTypeUv:        // Close the process's stdin. If the process doesn't close its own -      // stdout/stderr, they will be closed when it exits (voluntarily or not). -      process_close_in(proc); +      // stdout/stderr, they will be closed when it exits(possibly due to being +      // terminated after a timeout) +      stream_may_close(&proc->in);        ILOG("Sending SIGTERM to pid %d", proc->pid);        uv_kill(proc->pid, SIGTERM);        break; @@ -375,15 +358,15 @@ static void flush_stream(Process *proc, Stream *stream)      // Poll for data and process the generated events.      loop_poll_events(proc->loop, 0); -    if (proc->events) { -        multiqueue_process_events(proc->events); +    if (stream->events) { +        multiqueue_process_events(stream->events);      }      // Stream can be closed if it is empty.      if (num_bytes == stream->num_bytes) { -      if (stream->read_cb) { +      if (stream->read_cb && !stream->did_eof) {          // Stream callback could miss EOF handling if a child keeps the stream -        // open. +        // open. But only send EOF if we haven't already.          stream->read_cb(stream, stream->buffer, 0, stream->cb_data, true);        }        break; @@ -395,8 +378,8 @@ static void process_close_handles(void **argv)  {    Process *proc = argv[0]; -  flush_stream(proc, proc->out); -  flush_stream(proc, proc->err); +  flush_stream(proc, &proc->out); +  flush_stream(proc, &proc->err);    process_close_streams(proc);    process_close(proc);  | 
