mirror of
https://github.com/neovim/neovim.git
synced 2025-12-15 19:05:40 +00:00
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 <zeertzjq@outlook.com>
This commit is contained in:
@@ -312,6 +312,16 @@ describe(':terminal buffer', function()
|
||||
pcall_err(command, 'write test/functional/fixtures/tty-test.c')
|
||||
)
|
||||
end)
|
||||
|
||||
it('external interrupt (got_int) does not hang #20726', function()
|
||||
eq({ mode = 't', blocking = false }, api.nvim_get_mode())
|
||||
command('call timer_start(0, {-> interrupt()})')
|
||||
feed('<Ignore>') -- Add input to separate two RPC requests
|
||||
eq({ mode = 't', blocking = false }, api.nvim_get_mode())
|
||||
feed([[<C-\><C-N>]])
|
||||
eq({ mode = 'nt', blocking = false }, api.nvim_get_mode())
|
||||
command('bd!')
|
||||
end)
|
||||
end)
|
||||
|
||||
describe(':terminal buffer', function()
|
||||
|
||||
Reference in New Issue
Block a user