commit a626f783f82d71ba845bf96d2ce3f3c6b8f57a58
parent b6befc7b0333ede9f44df3527f304729fdfe8426
Author: zeertzjq <zeertzjq@outlook.com>
Date: Tue, 27 Jan 2026 13:49:32 +0800
Merge pull request #37578 from zeertzjq/term-title
Fix two other possible terminal crashes
Diffstat:
3 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
@@ -566,7 +566,7 @@ void terminal_open(Terminal **termpp, buf_T *buf, TerminalOptions opts)
aucmd_restbuf(&aco);
- if (*termpp == NULL) {
+ if (*termpp == NULL || term->buf_handle == 0) {
return; // Terminal has already been destroyed.
}
@@ -1416,6 +1416,7 @@ static void buf_set_term_title(buf_T *buf, const char *title, size_t len)
}
Error err = ERROR_INIT;
+ buf->b_locked++;
dict_set_var(buf->b_vars,
STATIC_CSTR_AS_STRING("term_title"),
STRING_OBJ(((String){ .data = (char *)title, .size = len })),
@@ -1423,6 +1424,7 @@ static void buf_set_term_title(buf_T *buf, const char *title, size_t len)
false,
NULL,
&err);
+ buf->b_locked--;
api_clear_error(&err);
status_redraw_buf(buf);
}
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
@@ -1134,6 +1134,16 @@ describe(':terminal buffer', function()
feed([[<C-\><C-N>]])
eq({ mode = 'nt', blocking = false }, api.nvim_get_mode())
end)
+
+ it('does not allow b:term_title watcher to delete buffer', function()
+ local chan = api.nvim_open_term(0, {})
+ api.nvim_chan_send(chan, '\027]2;SOME_TITLE\007')
+ eq('SOME_TITLE', api.nvim_buf_get_var(0, 'term_title'))
+ command([[call dictwatcheradd(b:, 'term_title', {-> execute('bwipe!')})]])
+ api.nvim_chan_send(chan, '\027]2;OTHER_TITLE\007')
+ eq('OTHER_TITLE', api.nvim_buf_get_var(0, 'term_title'))
+ matches('^E937: ', api.nvim_get_vvar('errmsg'))
+ end)
end)
describe('on_lines does not emit out-of-bounds line indexes when', function()
diff --git a/test/functional/terminal/channel_spec.lua b/test/functional/terminal/channel_spec.lua
@@ -213,6 +213,16 @@ describe('no crash when TermOpen autocommand', function()
]])
assert_alive()
end)
+
+ it('wipes buffer when using jobstart(…,{term=true}) during Nvim exit', function()
+ n.expect_exit(n.exec_lua, function()
+ vim.schedule(function()
+ vim.fn.jobstart(term_args, { term = true })
+ end)
+ vim.cmd('autocmd TermOpen * bwipe!')
+ vim.cmd('qall!')
+ end)
+ end)
end)
describe('nvim_open_term', function()