Mercurial > vim
diff src/window.c @ 34506:56ba5ea924a7 v9.1.0159
patch 9.1.0159: Crash in WinClosed after BufUnload closes other windows
Commit: https://github.com/vim/vim/commit/b2ec0da080fb24f12a8d6f54bd7318a078ca4e6c
Author: zeertzjq <zeertzjq@outlook.com>
Date: Sat Mar 9 15:39:27 2024 +0100
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>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sat, 09 Mar 2024 15:45:06 +0100 |
parents | 157cf882799f |
children | ad6cd802579d |
line wrap: on
line diff
--- a/src/window.c +++ b/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_ 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.