mirror of
https://github.com/neovim/neovim.git
synced 2025-12-14 18:35:47 +00:00
fix(api): on_detach consistently before buf_freeall autocmds (#35369)
Problem: on_detach may be called after buf_freeall and other important things,
plus its textlock restrictions are insufficient. This can cause issues such as
leaks, internal errors and crashes.
Solution: disable buffer updates in buf_freeall, before autocommands (like the
order after #35355 and when do_ecmd reloads a buffer). Don't do so in
free_buffer_stuff; it's not safe to run user code there, and buf_freeall already
runs before then; just free them to avoid leaks if buf_freeall autocommands
registered more for some reason.
(cherry picked from commit 2211953266)
Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
37b2d42459
commit
3ab06d5188
@@ -657,10 +657,6 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i
|
||||
|
||||
buf->b_nwindows = nwindows;
|
||||
|
||||
// Disable buffer-updates for the current buffer.
|
||||
// No need to check `unload_buf`: in that case the function returned above.
|
||||
buf_updates_unload(buf, false);
|
||||
|
||||
buf_freeall(buf, ((del_buf ? BFA_DEL : 0)
|
||||
+ (wipe_buf ? BFA_WIPE : 0)
|
||||
+ (ignore_abort ? BFA_IGNORE_ABORT : 0)));
|
||||
@@ -789,6 +785,11 @@ void buf_freeall(buf_T *buf, int flags)
|
||||
bufref_T bufref;
|
||||
set_bufref(&bufref, buf);
|
||||
|
||||
buf_updates_unload(buf, false);
|
||||
if (!bufref_valid(&bufref)) {
|
||||
// on_detach callback deleted the buffer.
|
||||
return;
|
||||
}
|
||||
if ((buf->b_ml.ml_mfp != NULL)
|
||||
&& apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, false, buf)
|
||||
&& !bufref_valid(&bufref)) {
|
||||
@@ -935,7 +936,7 @@ static void free_buffer_stuff(buf_T *buf, int free_flags)
|
||||
map_clear_mode(buf, MAP_ALL_MODES, true, true); // clear local abbrevs
|
||||
XFREE_CLEAR(buf->b_start_fenc);
|
||||
|
||||
buf_updates_unload(buf, false);
|
||||
buf_free_callbacks(buf);
|
||||
}
|
||||
|
||||
/// Go to another buffer. Handles the result of the ATTENTION dialog.
|
||||
|
||||
Reference in New Issue
Block a user