From 677eae6b0f84ebbc165a73aee65262d71af312cc Mon Sep 17 00:00:00 2001 From: oni-link Date: Fri, 20 May 2016 21:19:10 +0200 Subject: [PATCH 1/2] process.c: Fix a block when in teardown mode nvim blocking can be tested with "nvim +te +'!xclip' +qa" By closing all handles for a pty process, we unblock the event loop if the process has not terminated yet. --- src/nvim/event/process.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index 9bb62891c7..554a592d5c 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -116,18 +116,13 @@ void process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL process_is_tearing_down = true; kl_iter(WatcherPtr, loop->children, current) { Process *proc = (*current)->data; - if (proc->detach) { + if (proc->detach || proc->type == kProcessTypePty) { // Close handles to process without killing it. CREATE_EVENT(loop->events, process_close_handles, 1, proc); } else { - if (proc->type == kProcessTypeUv) { - uv_kill(proc->pid, SIGTERM); - proc->term_sent = true; - process_stop(proc); - } else { // kProcessTypePty - process_close_streams(proc); - pty_process_close_master((PtyProcess *)proc); - } + uv_kill(proc->pid, SIGTERM); + proc->term_sent = true; + process_stop(proc); } } @@ -315,8 +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. + if (process_is_tearing_down && (proc->detach || proc->type == kProcessTypePty) + && proc->closed) { + // If a detached/pty process dies while tearing down it might get closed + // twice. return; } assert(!proc->closed); From 1e593436d083f94d1e56f130ee498a9ff69736d7 Mon Sep 17 00:00:00 2001 From: oni-link Date: Fri, 27 May 2016 19:03:22 +0200 Subject: [PATCH 2/2] process.c: Close events are processed too late Compiling with macro -DEXITFREE opens a code path on which the event loop is used after it was teared down, because not all close events were processed yet. --- src/nvim/event/process.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index 554a592d5c..3c8c08e235 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -126,8 +126,10 @@ void process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL } } - // Wait until all children exit - LOOP_PROCESS_EVENTS_UNTIL(loop, loop->events, -1, kl_empty(loop->children)); + // Wait until all children exit and all close events are processed. + LOOP_PROCESS_EVENTS_UNTIL( + loop, loop->events, -1, + kl_empty(loop->children) && queue_empty(loop->events)); pty_process_teardown(loop); }