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:
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()