From 1d11808bfd2879bf278cd05a7095a6634fa5afec Mon Sep 17 00:00:00 2001 From: ibhagwan <59988195+ibhagwan@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:23:56 -0700 Subject: fix(terminal): interrupt/got_int hangs terminal (#30056) Upon `terminal_enter`, `mapped_ctrl_c` is set in order to avoid `CTRL-C` interrupts (which is proxied to the terminal process instead), `os_inchar` will then test `mapped_ctrl_c` against `State` and set `ctrl_c_interrupts=false` which prevents `process_ctrl_c` from setting `got_int=true` in a terminal state. However, if `got_int` is set outside of `process_ctrl_c`, e.g. via `interrupt()`, this will hang the neovim process as `terminal_execute` will enter an endless loop as `got_int` will never be cleared causing `safe_vgetc` to always return `Ctrl_C`. A minimal example reproducing this bug: ```vim :autocmd TermEnter * call timer_start(500, {-> interrupt()}) :terminal :startinsert ``` To fix, we make sure `got_int` is cleared inside `terminal_execute` when it detects `Ctrl_C`. Closes #20726 Co-authored-by: zeertzjq --- src/nvim/terminal.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 43f68f7321..ea3617098b 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -782,6 +782,12 @@ static int terminal_execute(VimState *state, int key) FALLTHROUGH; default: + if (key == Ctrl_C) { + // terminal_enter() always sets `mapped_ctrl_c` to avoid `got_int`. 8eeda7169aa4 + // But `got_int` may be set elsewhere, e.g. by interrupt() or an autocommand, + // so ensure that it is cleared. + got_int = false; + } if (key == Ctrl_BSL && !s->got_bsl) { s->got_bsl = true; break; -- cgit