mirror of
https://github.com/neovim/neovim.git
synced 2026-04-23 15:55:36 +00:00
fix(terminal): crash with race between buffer close and OSC 2 (#37225)
Problem: Crash when a terminal receives OSC 2 just after closing its
buffer but before terminal job exits.
Solution: Remove FUNC_ATTR_NONNULL_ALL from buf_set_term_title() and
check for NULL.
(cherry picked from commit b67ac8cc6b)
This commit is contained in:
committed by
github-actions[bot]
parent
f1641e6fc2
commit
ceed171485
@@ -1350,8 +1350,11 @@ static int term_movecursor(VTermPos new_pos, VTermPos old_pos, int visible, void
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void buf_set_term_title(buf_T *buf, const char *title, size_t len)
|
static void buf_set_term_title(buf_T *buf, const char *title, size_t len)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
|
||||||
{
|
{
|
||||||
|
if (!buf) {
|
||||||
|
return; // In case of receiving OSC 2 between buffer close and job exit.
|
||||||
|
}
|
||||||
|
|
||||||
Error err = ERROR_INIT;
|
Error err = ERROR_INIT;
|
||||||
dict_set_var(buf->b_vars,
|
dict_set_var(buf->b_vars,
|
||||||
STATIC_CSTR_AS_STRING("term_title"),
|
STATIC_CSTR_AS_STRING("term_title"),
|
||||||
@@ -1378,7 +1381,7 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *data)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VTERM_PROP_TITLE: {
|
case VTERM_PROP_TITLE: {
|
||||||
buf_T *buf = handle_get_buffer(term->buf_handle);
|
buf_T *buf = handle_get_buffer(term->buf_handle); // May be NULL
|
||||||
VTermStringFragment frag = val->string;
|
VTermStringFragment frag = val->string;
|
||||||
|
|
||||||
if (frag.initial && frag.final) {
|
if (frag.initial && frag.final) {
|
||||||
|
|||||||
@@ -431,6 +431,36 @@ describe(':terminal buffer', function()
|
|||||||
]])
|
]])
|
||||||
eq('TermLeave bar false', exec_lua('return _G.last_event'))
|
eq('TermLeave bar false', exec_lua('return _G.last_event'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('no crash with race between buffer close and OSC 2', function()
|
||||||
|
skip(is_os('win'), 'tty-test cannot forward OSC 2 on Windows?')
|
||||||
|
exec_lua(function()
|
||||||
|
vim.api.nvim_chan_send(vim.bo.channel, '\027]2;SOME_TITLE\007')
|
||||||
|
end)
|
||||||
|
retry(nil, 4000, function()
|
||||||
|
eq('SOME_TITLE', api.nvim_buf_get_var(0, 'term_title'))
|
||||||
|
end)
|
||||||
|
screen:expect_unchanged()
|
||||||
|
--- @type string
|
||||||
|
local title_before_del = exec_lua(function()
|
||||||
|
vim.wait(10) -- Ensure there are no pending events.
|
||||||
|
vim.api.nvim_chan_send(vim.bo.channel, '\027]2;OTHER_TITLE\007')
|
||||||
|
vim.uv.run('once') -- Only process the pending write.
|
||||||
|
vim.uv.sleep(50) -- Block the event loop and wait for tty-test to forward OSC 2.
|
||||||
|
local term_title = vim.b.term_title
|
||||||
|
vim.api.nvim_buf_delete(0, { force = true })
|
||||||
|
vim.wait(10, nil, nil, true) -- Process fast events only.
|
||||||
|
return term_title
|
||||||
|
end)
|
||||||
|
-- Title isn't changed until the second vim.wait().
|
||||||
|
eq('SOME_TITLE', title_before_del)
|
||||||
|
screen:expect([[
|
||||||
|
^ |
|
||||||
|
{4:~ }|*5
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
assert_alive()
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe(':terminal buffer', function()
|
describe(':terminal buffer', function()
|
||||||
|
|||||||
Reference in New Issue
Block a user