diff options
-rw-r--r-- | src/nvim/event/process.c | 27 | ||||
-rw-r--r-- | src/nvim/event/process.h | 3 | ||||
-rw-r--r-- | test/functional/autocmd/termclose_spec.lua | 6 |
3 files changed, 18 insertions, 18 deletions
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index 312da54c76..23433cf495 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -23,7 +23,7 @@ #endif // Time for a process to exit cleanly before we send KILL. -// For pty processes SIGTERM is sent first (in case SIGHUP was not enough). +// For PTY processes SIGTERM is sent first (in case SIGHUP was not enough). #define KILL_TIMEOUT_MS 2000 static bool process_is_tearing_down = false; @@ -209,8 +209,8 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL if (exited || proc->stopped_time) { return; } - proc->stopped_time = os_hrtime(); + switch (proc->type) { case kProcessTypeUv: // Close the process's stdin. If the process doesn't close its own @@ -228,18 +228,16 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL abort(); } - // Start a timer to verify that the job process terminated. - ILOG("starting job kill timer"); + // (Re)start timer to verify that stopped process(es) died. uv_timer_start(&proc->loop->children_kill_timer, children_kill_cb, KILL_TIMEOUT_MS, 0); } -/// Sends SIGKILL (or SIGTERM for PTY jobs) to processes that didn't terminate -/// after process_stop() requested them. +/// Sends SIGKILL (or SIGTERM..SIGKILL for PTY jobs) to processes that did +/// not terminate after process_stop(). static void children_kill_cb(uv_timer_t *handle) { Loop *loop = handle->loop->data; - uint64_t now = os_hrtime(); kl_iter(WatcherPtr, loop->children, current) { Process *proc = (*current)->data; @@ -247,12 +245,15 @@ static void children_kill_cb(uv_timer_t *handle) if (exited || !proc->stopped_time) { continue; } - uint64_t elapsed = (now - proc->stopped_time) / 1000000 + 1; - if (elapsed >= KILL_TIMEOUT_MS) { - int sig = proc->type == kProcessTypePty && elapsed < KILL_TIMEOUT_MS * 2 - ? SIGTERM - : SIGKILL; - os_proc_tree_kill(proc->pid, sig); + uint64_t term_sent = UINT64_MAX == proc->stopped_time; + if (kProcessTypePty != proc->type || term_sent) { + os_proc_tree_kill(proc->pid, SIGKILL); + } else { + os_proc_tree_kill(proc->pid, SIGTERM); + proc->stopped_time = UINT64_MAX; // Flag: SIGTERM was sent. + // Restart timer. + uv_timer_start(&proc->loop->children_kill_timer, children_kill_cb, + KILL_TIMEOUT_MS, 0); } } } diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h index 033ce3604b..ba2c2a6a11 100644 --- a/src/nvim/event/process.h +++ b/src/nvim/event/process.h @@ -19,8 +19,7 @@ struct process { Loop *loop; void *data; int pid, status, refcount; - // set to the hrtime of when process_stop was called for the process. - uint64_t stopped_time; + uint64_t stopped_time; // process_stop() timestamp const char *cwd; char **argv; Stream in, out, err; diff --git a/test/functional/autocmd/termclose_spec.lua b/test/functional/autocmd/termclose_spec.lua index 0804579a4f..db4e5379d0 100644 --- a/test/functional/autocmd/termclose_spec.lua +++ b/test/functional/autocmd/termclose_spec.lua @@ -32,7 +32,7 @@ describe('TermClose event', function() end) it('kills job trapping SIGTERM', function() - if helpers.pending_win32(pending) then return end + if iswin() then return end nvim('set_option', 'shell', 'sh') nvim('set_option', 'shellcmdflag', '-c') command([[ let g:test_job = jobstart('trap "" TERM && echo 1 && sleep 60', { ]] @@ -51,8 +51,8 @@ describe('TermClose event', function() ok(duration <= 4000) -- Epsilon for slow CI end) - it('kills pty job trapping SIGHUP and SIGTERM', function() - if helpers.pending_win32(pending) then return end + it('kills PTY job trapping SIGHUP and SIGTERM', function() + if iswin() then return end nvim('set_option', 'shell', 'sh') nvim('set_option', 'shellcmdflag', '-c') command([[ let g:test_job = jobstart('trap "" HUP TERM && echo 1 && sleep 60', { ]] |