diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-09-23 07:14:32 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2022-09-23 07:38:22 +0800 |
commit | c28f00b101148d17a640fe2a186b23fbe230fbf3 (patch) | |
tree | 61d3ff2d9240ab65ec2200efbe14c966b976b471 | |
parent | 0760379b413ca95b80ed2970b49f14ba3b1acbf9 (diff) | |
download | rneovim-c28f00b101148d17a640fe2a186b23fbe230fbf3.tar.gz rneovim-c28f00b101148d17a640fe2a186b23fbe230fbf3.tar.bz2 rneovim-c28f00b101148d17a640fe2a186b23fbe230fbf3.zip |
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)
https://github.com/vim/vim/commit/62de54b48d6354d4622ec0b21ffa4cf3cf312505
-rw-r--r-- | src/nvim/ex_docmd.c | 6 | ||||
-rw-r--r-- | src/nvim/testdir/test_autocmd.vim | 20 | ||||
-rw-r--r-- | src/nvim/window.c | 21 |
3 files changed, 29 insertions, 18 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index b01a262f84..085948f7b1 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -4696,7 +4696,6 @@ void tabpage_close(int forceit) void tabpage_close_other(tabpage_T *tp, int forceit) { int done = 0; - int h = tabline_height(); char prev_idx[NUMBUFLEN]; // 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; } } - - redraw_tabline = true; - if (h != tabline_height()) { - win_new_screen_rows(); - } } /// ":only". diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index 1be2d11034..d766256d4b 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -447,6 +447,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/nvim/window.c b/src/nvim/window.c index 236663dfea..22c1b77570 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2439,7 +2439,6 @@ void curwin_init(void) void close_windows(buf_T *buf, bool keep_curwin) { tabpage_T *tp, *nexttp; - int h = tabline_height(); RedrawingDisabled++; @@ -2480,11 +2479,6 @@ void close_windows(buf_T *buf, bool keep_curwin) } RedrawingDisabled--; - - redraw_tabline = true; - if (h != tabline_height()) { - win_new_screen_rows(); - } } /// 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 // that below. goto_tabpage_tp(alt_tabpage(), false, true); - redraw_tabline = true; // save index for tabclosed event 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 // 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()) { - win_new_screen_rows(); - } } 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) && 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; } @@ -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)); } + int h = tabline_height(); + if (tp == first_tabpage) { first_tabpage = tp->tp_next; } else { @@ -3004,6 +2997,10 @@ void 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()) { + win_new_screen_rows(); + } if (has_event(EVENT_TABCLOSED)) { apply_autocmds(EVENT_TABCLOSED, prev_idx, prev_idx, false, win->w_buffer); |