mirror of
https://github.com/neovim/neovim.git
synced 2025-09-09 12:58:16 +00:00
fix(buffer): disable buffer-updates before removing buffer from window
There can be other places that access window buffer info (e.g.
`tabpagebuflist()`), so checking `w_closing` in `win_findbuf()` doesn't
solve the crash in all cases, and may also cause Nvim's behavior to
diverge from Vim.
(cherry picked from commit fa30ef1c31
)
This commit is contained in:

committed by
github-actions[bot]
![github-actions[bot]](/assets/img/avatar_default.png)
parent
1dba6cf8f0
commit
05f6883ee2
@@ -578,6 +578,10 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable buffer-updates for the current buffer.
|
||||||
|
// No need to check `unload_buf`: in that case the function returned above.
|
||||||
|
buf_updates_unload(buf, false);
|
||||||
|
|
||||||
if (win != NULL // Avoid bogus clang warning.
|
if (win != NULL // Avoid bogus clang warning.
|
||||||
&& win_valid_any_tab(win)
|
&& win_valid_any_tab(win)
|
||||||
&& win->w_buffer == buf) {
|
&& win->w_buffer == buf) {
|
||||||
@@ -590,10 +594,6 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i
|
|||||||
buf->b_nwindows--;
|
buf->b_nwindows--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable buffer-updates for the current buffer.
|
|
||||||
// No need to check `unload_buf`: in that case the function returned above.
|
|
||||||
buf_updates_unload(buf, false);
|
|
||||||
|
|
||||||
// Remove the buffer from the list.
|
// Remove the buffer from the list.
|
||||||
if (wipe_buf) {
|
if (wipe_buf) {
|
||||||
// Do not wipe out the buffer if it is used in a window.
|
// Do not wipe out the buffer if it is used in a window.
|
||||||
|
@@ -7207,7 +7207,7 @@ void win_findbuf(typval_T *argvars, list_T *list)
|
|||||||
int bufnr = tv_get_number(&argvars[0]);
|
int bufnr = tv_get_number(&argvars[0]);
|
||||||
|
|
||||||
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
||||||
if (!wp->w_closing && wp->w_buffer->b_fnum == bufnr) {
|
if (wp->w_buffer->b_fnum == bufnr) {
|
||||||
tv_list_append_number(list, wp->handle);
|
tv_list_append_number(list, wp->handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -252,9 +252,8 @@ describe('lua buffer event callbacks: on_lines', function()
|
|||||||
eq(2, meths.win_get_cursor(0)[1])
|
eq(2, meths.win_get_cursor(0)[1])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('does not SEGFAULT when calling win_findbuf in on_detach', function()
|
it('does not SEGFAULT when accessing window buffer info in on_detach #14998', function()
|
||||||
|
local code = [[
|
||||||
exec_lua[[
|
|
||||||
local buf = vim.api.nvim_create_buf(false, false)
|
local buf = vim.api.nvim_create_buf(false, false)
|
||||||
|
|
||||||
vim.cmd"split"
|
vim.cmd"split"
|
||||||
@@ -262,13 +261,19 @@ describe('lua buffer event callbacks: on_lines', function()
|
|||||||
|
|
||||||
vim.api.nvim_buf_attach(buf, false, {
|
vim.api.nvim_buf_attach(buf, false, {
|
||||||
on_detach = function(_, buf)
|
on_detach = function(_, buf)
|
||||||
|
vim.fn.tabpagebuflist()
|
||||||
vim.fn.win_findbuf(buf)
|
vim.fn.win_findbuf(buf)
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
exec_lua(code)
|
||||||
command("q!")
|
command("q!")
|
||||||
helpers.assert_alive()
|
helpers.assert_alive()
|
||||||
|
|
||||||
|
exec_lua(code)
|
||||||
|
command("bd!")
|
||||||
|
helpers.assert_alive()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('#12718 lnume', function()
|
it('#12718 lnume', function()
|
||||||
|
Reference in New Issue
Block a user