diff options
Diffstat (limited to 'src/nvim/event')
-rw-r--r-- | src/nvim/event/libuv_process.c | 3 | ||||
-rw-r--r-- | src/nvim/event/process.c | 18 | ||||
-rw-r--r-- | src/nvim/event/process.h | 5 |
3 files changed, 21 insertions, 5 deletions
diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c index 44305c69bc..9ef3468284 100644 --- a/src/nvim/event/libuv_process.c +++ b/src/nvim/event/libuv_process.c @@ -21,6 +21,9 @@ bool libuv_process_spawn(LibuvProcess *uvproc) uvproc->uvopts.args = proc->argv; uvproc->uvopts.flags = UV_PROCESS_WINDOWS_HIDE | UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS; + if (proc->detach) { + uvproc->uvopts.flags |= UV_PROCESS_DETACHED; + } uvproc->uvopts.exit_cb = exit_cb; uvproc->uvopts.cwd = NULL; uvproc->uvopts.env = NULL; diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index 0336eb880a..d365a78a9d 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -29,6 +29,7 @@ } \ } while (0) +static bool process_is_tearing_down = false; bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL { @@ -112,11 +113,17 @@ bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL void process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL { + process_is_tearing_down = true; kl_iter(WatcherPtr, loop->children, current) { Process *proc = (*current)->data; - uv_kill(proc->pid, SIGTERM); - proc->term_sent = true; - process_stop(proc); + if (proc->detach) { + // Close handles to process without killing it. + CREATE_EVENT(loop->events, process_close_handles, 1, proc); + } else { + uv_kill(proc->pid, SIGTERM); + proc->term_sent = true; + process_stop(proc); + } } // Wait until all children exit @@ -303,6 +310,10 @@ static void decref(Process *proc) static void process_close(Process *proc) FUNC_ATTR_NONNULL_ARG(1) { + if (process_is_tearing_down && proc->detach && proc->closed) { + // If a detached process dies while tearing down it might get closed twice. + return; + } assert(!proc->closed); proc->closed = true; switch (proc->type) { @@ -333,6 +344,7 @@ static void on_process_exit(Process *proc) DLOG("Stopping process kill timer"); uv_timer_stop(&loop->children_kill_timer); } + // Process handles are closed in the next event loop tick. This is done to // give libuv more time to read data from the OS after the process exits(If // process_close_streams is called with data still in the OS buffer, we lose diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h index 45edc46b95..e23c8ea60f 100644 --- a/src/nvim/event/process.h +++ b/src/nvim/event/process.h @@ -25,7 +25,7 @@ struct process { Stream *in, *out, *err; process_exit_cb cb; internal_process_cb internal_exit_cb, internal_close_cb; - bool closed, term_sent; + bool closed, term_sent, detach; Queue *events; }; @@ -48,7 +48,8 @@ static inline Process process_init(Loop *loop, ProcessType type, void *data) .closed = false, .term_sent = false, .internal_close_cb = NULL, - .internal_exit_cb = NULL + .internal_exit_cb = NULL, + .detach = false }; } |