mirror of
https://github.com/vim/vim.git
synced 2025-07-04 23:07:33 -04:00
patch 9.1.0159: Crash in WinClosed after BufUnload closes other windows
Problem: Crash in WinClosed after BufUnload closes other windows Solution: Don't trigger WinClosed if the buffer is NULL (zeertzjq) Now win_close_othertab() doesn't trigger any autocommands if the buffer is NULL, so remove the autocmd blocking above (which was added not long ago in patch v9.0.0550) for consistency. Also remove an unreachable close_last_window_tabpage() above: - It is only reached if only_one_window() returns TRUE and last_window() returns FALSE. - If only_one_window() returns TRUE, there is only one tabpage. - If there is only one tabpage and last_window() returns FALSE, the one_window() in last_window() must return FALSE, and the ONE_WINDOW in close_last_window_tabpage() must also be FALSE. - So close_last_window_tabpage() doesn't do anything and returns FALSE. Then the curtab != prev_curtab check also doesn't make much sense, and the only_one_window() can be replaced with a check for popup and a call to last_window() since this is a stricter check than only_one_window(). closes: #14166 Signed-off-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
parent
8a01744c56
commit
b2ec0da080
@ -819,6 +819,27 @@ func Test_WinClosed_switch_tab()
|
||||
%bwipe!
|
||||
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_BufUnload_close_other()
|
||||
tabnew
|
||||
let g:tab = tabpagenr()
|
||||
let g:buf = bufnr()
|
||||
new
|
||||
setlocal bufhidden=wipe
|
||||
augroup test-WinClosed
|
||||
autocmd BufUnload * ++once exe g:buf .. 'bwipe!'
|
||||
autocmd WinClosed * call tabpagebuflist(g:tab)
|
||||
augroup END
|
||||
close
|
||||
|
||||
unlet g:tab
|
||||
unlet g:buf
|
||||
autocmd! test-WinClosed
|
||||
augroup! test-WinClosed
|
||||
%bwipe!
|
||||
endfunc
|
||||
|
||||
func s:AddAnAutocmd()
|
||||
augroup vimBarTest
|
||||
au BufReadCmd * echo 'hello'
|
||||
|
@ -704,6 +704,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
159,
|
||||
/**/
|
||||
158,
|
||||
/**/
|
||||
|
28
src/window.c
28
src/window.c
@ -2585,7 +2585,7 @@ one_window(void)
|
||||
|
||||
/*
|
||||
* Close the possibly last window in a tab page.
|
||||
* Returns TRUE when the window was closed already.
|
||||
* Return FALSE if there are other windows and nothing is done, TRUE otherwise.
|
||||
*/
|
||||
static int
|
||||
close_last_window_tabpage(
|
||||
@ -2723,7 +2723,7 @@ win_close(win_T *win, int free_buf)
|
||||
// and then close the window and the tab page to avoid that curwin and
|
||||
// curtab are invalid while we are freeing memory.
|
||||
if (close_last_window_tabpage(win, free_buf, prev_curtab))
|
||||
return FAIL;
|
||||
return FAIL;
|
||||
|
||||
// When closing the help window, try restoring a snapshot after closing
|
||||
// the window. Otherwise clear the snapshot, it's now invalid.
|
||||
@ -2796,9 +2796,11 @@ win_close(win_T *win, int free_buf)
|
||||
|
||||
win_close_buffer(win, free_buf ? DOBUF_UNLOAD : 0, TRUE);
|
||||
|
||||
if (only_one_window() && win_valid(win) && win->w_buffer == NULL
|
||||
&& (last_window() || curtab != prev_curtab
|
||||
|| close_last_window_tabpage(win, free_buf, prev_curtab)))
|
||||
if (win_valid(win) && win->w_buffer == NULL
|
||||
#if defined(FEAT_PROP_POPUP)
|
||||
&& !popup_is_popup(win)
|
||||
#endif
|
||||
&& last_window())
|
||||
{
|
||||
// Autocommands have closed all windows, quit now. Restore
|
||||
// curwin->w_buffer, otherwise writing viminfo may fail.
|
||||
@ -2812,10 +2814,7 @@ 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;
|
||||
}
|
||||
|
||||
@ -3352,10 +3351,15 @@ win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
|
||||
return; // window is already being closed
|
||||
|
||||
// Trigger WinClosed just before starting to free window-related resources.
|
||||
trigger_winclosed(win);
|
||||
// autocmd may have freed the window already.
|
||||
if (!win_valid_any_tab(win))
|
||||
return;
|
||||
// If the buffer is NULL, it isn't safe to trigger autocommands,
|
||||
// and win_close() should have already triggered WinClosed.
|
||||
if (win->w_buffer != NULL)
|
||||
{
|
||||
trigger_winclosed(win);
|
||||
// autocmd may have freed the window already.
|
||||
if (!win_valid_any_tab(win))
|
||||
return;
|
||||
}
|
||||
|
||||
if (win->w_buffer != NULL)
|
||||
// Close the link to the buffer.
|
||||
|
Loading…
x
Reference in New Issue
Block a user