mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 11:28:22 +00:00
vim-patch:9.0.0550: crash when closing a tabpage and buffer is NULL
Problem: Crash when closing a tabpage and buffer is NULL.
Solution: Adjust how autocommands are triggered when closing a window.
(closes vim/vim#11198, closes vim/vim#11197)
62de54b48d
This commit is contained in:
@@ -4696,7 +4696,6 @@ void tabpage_close(int forceit)
|
|||||||
void tabpage_close_other(tabpage_T *tp, int forceit)
|
void tabpage_close_other(tabpage_T *tp, int forceit)
|
||||||
{
|
{
|
||||||
int done = 0;
|
int done = 0;
|
||||||
int h = tabline_height();
|
|
||||||
char prev_idx[NUMBUFLEN];
|
char prev_idx[NUMBUFLEN];
|
||||||
|
|
||||||
// Limit to 1000 windows, autocommands may add a window while we close
|
// Limit to 1000 windows, autocommands may add a window while we close
|
||||||
@@ -4712,11 +4711,6 @@ void tabpage_close_other(tabpage_T *tp, int forceit)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
redraw_tabline = true;
|
|
||||||
if (h != tabline_height()) {
|
|
||||||
win_new_screen_rows();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ":only".
|
/// ":only".
|
||||||
|
@@ -447,6 +447,26 @@ func Test_WinClosed_throws_with_tabs()
|
|||||||
augroup! test-WinClosed
|
augroup! test-WinClosed
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" This used to trigger WinClosed twice for the same window, and the window's
|
||||||
|
" buffer was NULL in the second autocommand.
|
||||||
|
func Test_WinClosed_switch_tab()
|
||||||
|
edit Xa
|
||||||
|
split Xb
|
||||||
|
split Xc
|
||||||
|
tab split
|
||||||
|
new
|
||||||
|
augroup test-WinClosed
|
||||||
|
autocmd WinClosed * tabprev | bwipe!
|
||||||
|
augroup END
|
||||||
|
close
|
||||||
|
" Check that the tabline has been fully removed
|
||||||
|
call assert_equal([1, 1], win_screenpos(0))
|
||||||
|
|
||||||
|
autocmd! test-WinClosed
|
||||||
|
augroup! test-WinClosed
|
||||||
|
%bwipe!
|
||||||
|
endfunc
|
||||||
|
|
||||||
func s:AddAnAutocmd()
|
func s:AddAnAutocmd()
|
||||||
augroup vimBarTest
|
augroup vimBarTest
|
||||||
au BufReadCmd * echo 'hello'
|
au BufReadCmd * echo 'hello'
|
||||||
|
@@ -2439,7 +2439,6 @@ void curwin_init(void)
|
|||||||
void close_windows(buf_T *buf, bool keep_curwin)
|
void close_windows(buf_T *buf, bool keep_curwin)
|
||||||
{
|
{
|
||||||
tabpage_T *tp, *nexttp;
|
tabpage_T *tp, *nexttp;
|
||||||
int h = tabline_height();
|
|
||||||
|
|
||||||
RedrawingDisabled++;
|
RedrawingDisabled++;
|
||||||
|
|
||||||
@@ -2480,11 +2479,6 @@ void close_windows(buf_T *buf, bool keep_curwin)
|
|||||||
}
|
}
|
||||||
|
|
||||||
RedrawingDisabled--;
|
RedrawingDisabled--;
|
||||||
|
|
||||||
redraw_tabline = true;
|
|
||||||
if (h != tabline_height()) {
|
|
||||||
win_new_screen_rows();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check that the specified window is the last one.
|
/// Check that the specified window is the last one.
|
||||||
@@ -2575,7 +2569,6 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev
|
|||||||
// Don't trigger autocommands yet, they may use wrong values, so do
|
// Don't trigger autocommands yet, they may use wrong values, so do
|
||||||
// that below.
|
// that below.
|
||||||
goto_tabpage_tp(alt_tabpage(), false, true);
|
goto_tabpage_tp(alt_tabpage(), false, true);
|
||||||
redraw_tabline = true;
|
|
||||||
|
|
||||||
// save index for tabclosed event
|
// save index for tabclosed event
|
||||||
char_u prev_idx[NUMBUFLEN];
|
char_u prev_idx[NUMBUFLEN];
|
||||||
@@ -2584,12 +2577,7 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev
|
|||||||
// Safety check: Autocommands may have closed the window when jumping
|
// Safety check: Autocommands may have closed the window when jumping
|
||||||
// to the other tab page.
|
// to the other tab page.
|
||||||
if (valid_tabpage(prev_curtab) && prev_curtab->tp_firstwin == win) {
|
if (valid_tabpage(prev_curtab) && prev_curtab->tp_firstwin == win) {
|
||||||
int h = tabline_height();
|
|
||||||
|
|
||||||
win_close_othertab(win, free_buf, prev_curtab);
|
win_close_othertab(win, free_buf, prev_curtab);
|
||||||
if (h != tabline_height()) {
|
|
||||||
win_new_screen_rows();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
entering_window(curwin);
|
entering_window(curwin);
|
||||||
|
|
||||||
@@ -2793,7 +2781,10 @@ int win_close(win_T *win, bool free_buf, bool force)
|
|||||||
if (curtab != prev_curtab && win_valid_any_tab(win)
|
if (curtab != prev_curtab && win_valid_any_tab(win)
|
||||||
&& win->w_buffer == NULL) {
|
&& win->w_buffer == NULL) {
|
||||||
// Need to close the window anyway, since the buffer is NULL.
|
// Need to close the window anyway, since the buffer is NULL.
|
||||||
|
// Don't trigger autocmds with a NULL buffer.
|
||||||
|
block_autocmds();
|
||||||
win_close_othertab(win, false, prev_curtab);
|
win_close_othertab(win, false, prev_curtab);
|
||||||
|
unblock_autocmds();
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2990,6 +2981,8 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
|
|||||||
vim_snprintf(prev_idx, NUMBUFLEN, "%i", tabpage_index(tp));
|
vim_snprintf(prev_idx, NUMBUFLEN, "%i", tabpage_index(tp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int h = tabline_height();
|
||||||
|
|
||||||
if (tp == first_tabpage) {
|
if (tp == first_tabpage) {
|
||||||
first_tabpage = tp->tp_next;
|
first_tabpage = tp->tp_next;
|
||||||
} else {
|
} else {
|
||||||
@@ -3004,6 +2997,10 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
|
|||||||
ptp->tp_next = tp->tp_next;
|
ptp->tp_next = tp->tp_next;
|
||||||
}
|
}
|
||||||
free_tp = true;
|
free_tp = true;
|
||||||
|
redraw_tabline = true;
|
||||||
|
if (h != tabline_height()) {
|
||||||
|
win_new_screen_rows();
|
||||||
|
}
|
||||||
|
|
||||||
if (has_event(EVENT_TABCLOSED)) {
|
if (has_event(EVENT_TABCLOSED)) {
|
||||||
apply_autocmds(EVENT_TABCLOSED, prev_idx, prev_idx, false, win->w_buffer);
|
apply_autocmds(EVENT_TABCLOSED, prev_idx, prev_idx, false, win->w_buffer);
|
||||||
|
Reference in New Issue
Block a user