summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-09-22 18:08:37 +0100
committerBram Moolenaar <Bram@vim.org>2022-09-22 18:08:37 +0100
commit62de54b48d6354d4622ec0b21ffa4cf3cf312505 (patch)
tree1aa6e8b6c74a1fa1514279b4389681c93fa8b413
parent5800c798385b4a7eded9ea63cfd4f57d1499a673 (diff)
patch 9.0.0550: crash when closing a tabpage and buffer is NULLv9.0.0550
Problem: Crash when closing a tabpage and buffer is NULL. Solution: Adjust how autocommands are triggered when closing a window. (closes #11198, closes #11197)
-rw-r--r--src/ex_docmd.c5
-rw-r--r--src/testdir/test_autocmd.vim20
-rw-r--r--src/version.c2
-rw-r--r--src/window.c20
4 files changed, 30 insertions, 17 deletions
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index a786ff0cc6..912203917e 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -6304,7 +6304,6 @@ tabpage_close_other(tabpage_T *tp, int forceit)
{
int done = 0;
win_T *wp;
- int h = tabline_height();
// Limit to 1000 windows, autocommands may add a window while we close
// one. OK, so I'm paranoid...
@@ -6320,10 +6319,6 @@ tabpage_close_other(tabpage_T *tp, int forceit)
}
apply_autocmds(EVENT_TABCLOSED, NULL, NULL, FALSE, curbuf);
-
- redraw_tabline = TRUE;
- if (h != tabline_height())
- shell_new_rows();
}
/*
diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim
index 17bfd1b60b..3c95f87a3d 100644
--- a/src/testdir/test_autocmd.vim
+++ b/src/testdir/test_autocmd.vim
@@ -515,6 +515,26 @@ func Test_WinClosed_throws_with_tabs()
augroup! test-WinClosed
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()
augroup vimBarTest
au BufReadCmd * echo 'hello'
diff --git a/src/version.c b/src/version.c
index e3a3a0e45a..5d6951c879 100644
--- a/src/version.c
+++ b/src/version.c
@@ -700,6 +700,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 550,
+/**/
549,
/**/
548,
diff --git a/src/window.c b/src/window.c
index 3e1a3efd86..d73dfd9fd0 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2340,7 +2340,6 @@ close_windows(
{
win_T *wp;
tabpage_T *tp, *nexttp;
- int h = tabline_height();
int count = tabpage_index(NULL);
++RedrawingDisabled;
@@ -2384,10 +2383,6 @@ close_windows(
if (count != tabpage_index(NULL))
apply_autocmds(EVENT_TABCLOSED, NULL, NULL, FALSE, curbuf);
-
- redraw_tabline = TRUE;
- if (h != tabline_height())
- shell_new_rows();
}
/*
@@ -2446,18 +2441,11 @@ close_last_window_tabpage(
* that below.
*/
goto_tabpage_tp(alt_tabpage(), FALSE, TRUE);
- redraw_tabline = TRUE;
// Safety check: Autocommands may have closed the window when jumping
// to the other tab page.
if (valid_tabpage(prev_curtab) && prev_curtab->tp_firstwin == win)
- {
- int h = tabline_height();
-
win_close_othertab(win, free_buf, prev_curtab);
- if (h != tabline_height())
- shell_new_rows();
- }
#ifdef FEAT_JOB_CHANNEL
entering_window(curwin);
#endif
@@ -2656,7 +2644,10 @@ win_close(win_T *win, int free_buf)
&& win->w_buffer == 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);
+ unblock_autocmds();
return FAIL;
}
@@ -2907,6 +2898,8 @@ win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
// When closing the last window in a tab page remove the tab page.
if (tp->tp_firstwin == tp->tp_lastwin)
{
+ int h = tabline_height();
+
if (tp == first_tabpage)
first_tabpage = tp->tp_next;
else
@@ -2922,6 +2915,9 @@ win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
ptp->tp_next = tp->tp_next;
}
free_tp = TRUE;
+ redraw_tabline = TRUE;
+ if (h != tabline_height())
+ shell_new_rows();
}
// Free the memory used for the window.