vim-patch:9.1.1773: Crash in BufLeave after BufUnload closes other windows (#35830)

Problem:  Crash in BufLeave/WinLeave/TabLeave when closing window after
          BufUnload closes all other windows in the tab page.
Solution: Avoid duplicate BufLeave/WinLeave events. Trigger TabLeave
          before removing the buffer (zeertzjq).

related: vim/vim#14166
related: neovim/neovim#33603
closes: vim/vim#18330

0c70820015
(cherry picked from commit c9f6267402)
This commit is contained in:
zeertzjq
2025-09-19 07:40:12 +08:00
committed by github-actions[bot]
parent 556d8d0002
commit 77fe01f200
2 changed files with 47 additions and 15 deletions

View File

@@ -2610,9 +2610,11 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev
// page and then close the window and the tab page. This avoids that
// curwin and curtab are invalid while we are freeing memory, they may
// be used in GUI events.
// Don't trigger autocommands yet, they may use wrong values, so do
// Don't trigger *Enter autocommands yet, they may use wrong values, so do
// that below.
goto_tabpage_tp(alt_tabpage(), false, true);
// Do trigger *Leave autocommands, unless win->w_buffer is NULL, in which
// case they have already been triggered.
goto_tabpage_tp(alt_tabpage(), false, win->w_buffer != NULL);
// Safety check: Autocommands may have closed the window when jumping
// to the other tab page.
@@ -2906,6 +2908,14 @@ int win_close(win_T *win, bool free_buf, bool force)
}
}
if (ONE_WINDOW && curwin->w_locked && curbuf->b_locked_split
&& first_tabpage->tp_next != NULL) {
// The new curwin is the last window in the current tab page, and it is
// already being closed. Trigger TabLeave now, as after its buffer is
// removed it's no longer safe to do that.
apply_autocmds(EVENT_TABLEAVE, NULL, NULL, false, curbuf);
}
split_disallowed--;
// After closing the help window, try restoring the window layout from