neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit 1519a34e43df315649ba09d4865d4dd4268a76b4
parent da8de99d0bdc6684213de54905c56ca827a8836f
Author: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Date:   Sat,  7 Feb 2026 19:40:24 +0000

fix(terminal): autocmds leave terminal open to wiped buffer

Problem: if buf_free_all autocommands open a terminal, it will remain open after
the buffer is freed.

Solution: close terminals again later, this time while blocking autocommands.

Did consider terminal_open checking stuff like b_locked_split instead, but
that's set during BufHidden, etc., which doesn't mean the buffer's being wiped.

Diffstat:
Msrc/nvim/buffer.c | 7+++++++
Mtest/functional/terminal/channel_spec.lua | 10++++++++++
2 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c @@ -902,6 +902,13 @@ void buf_freeall(buf_T *buf, int flags) } } + // Autocommands may have opened another terminal. Block them this time. + if (buf->terminal) { + block_autocmds(); + buf_close_terminal(buf); + unblock_autocmds(); + } + ml_close(buf, true); // close and delete the memline/memfile buf->b_ml.ml_line_count = 0; // no lines in buffer if ((flags & BFA_KEEP_UNDO) == 0) { diff --git a/test/functional/terminal/channel_spec.lua b/test/functional/terminal/channel_spec.lua @@ -34,6 +34,16 @@ describe('terminal channel is closed and later released if', function() feed('<Ignore>') -- add input to separate two RPC requests -- channel has been released after one main loop iteration eq(chans - 1, eval('len(nvim_list_chans())')) + + command('autocmd BufWipeout * ++once let id2 = nvim_open_term(str2nr(expand("<abuf>")), {})') + -- channel hasn't been released yet + eq( + "Vim(call):Can't send data to closed stream", + pcall_err(command, [[bdelete! | call chansend(id2, 'test')]]) + ) + feed('<Ignore>') -- add input to separate two RPC requests + -- channel has been released after one main loop iteration + eq(chans - 1, eval('len(nvim_list_chans())')) end) it('opened by nvim_open_term(), closed by chanclose(), and deleted by pressing a key', function()