aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buffer.c24
-rw-r--r--src/ex_cmds.c5
-rw-r--r--src/fileio.c11
-rw-r--r--src/globals.h5
-rw-r--r--src/version.c2
5 files changed, 39 insertions, 8 deletions
diff --git a/src/buffer.c b/src/buffer.c
index d25ed10ac7..7402c57ec8 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -550,7 +550,14 @@ static void free_buffer(buf_T *buf)
free_buffer_stuff(buf, TRUE);
unref_var_dict(buf->b_vars);
aubuflocal_remove(buf);
- vim_free(buf);
+ if (autocmd_busy) {
+ // Do not free the buffer structure while autocommands are executing,
+ // it's still needed. Free it when autocmd_busy is reset.
+ buf->b_next = au_pending_free_buf;
+ au_pending_free_buf = buf;
+ } else {
+ vim_free(buf);
+ }
}
/*
@@ -1332,8 +1339,12 @@ buflist_new (
buf_copy_options(buf, 0);
if ((flags & BLN_LISTED) && !buf->b_p_bl) {
buf->b_p_bl = TRUE;
- if (!(flags & BLN_DUMMY))
+ if (!(flags & BLN_DUMMY)) {
apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf);
+ if (!buf_valid(buf)) {
+ return NULL;
+ }
+ }
}
return buf;
}
@@ -1469,8 +1480,15 @@ buflist_new (
buf->b_p_bl = (flags & BLN_LISTED) ? TRUE : FALSE; /* init 'buflisted' */
if (!(flags & BLN_DUMMY)) {
apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, buf);
- if (flags & BLN_LISTED)
+ if (!buf_valid(buf)) {
+ return NULL;
+ }
+ if (flags & BLN_LISTED) {
apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf);
+ if (!buf_valid(buf)) {
+ return NULL;
+ }
+ }
if (aborting()) /* autocmds may abort script processing */
return NULL;
}
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index e3d02357e1..0779568bc8 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -2774,6 +2774,11 @@ do_ecmd (
}
buf = buflist_new(ffname, sfname, 0L,
BLN_CURBUF | ((flags & ECMD_SET_HELP) ? 0 : BLN_LISTED));
+ // Autocmds may change curwin and curbuf.
+ if (oldwin != NULL) {
+ oldwin = curwin;
+ }
+ old_curbuf = curbuf;
}
if (buf == NULL)
goto theend;
diff --git a/src/fileio.c b/src/fileio.c
index fb9f0e0cea..68b68ef3ed 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -7525,14 +7525,17 @@ apply_autocmds_group (
vim_free(sfname);
--nesting; /* see matching increment above */
- /*
- * When stopping to execute autocommands, restore the search patterns and
- * the redo buffer.
- */
+ // When stopping to execute autocommands, restore the search patterns and
+ // the redo buffer. Free buffers in the au_pending_free_buf list.
if (!autocmd_busy) {
restore_search_patterns();
restoreRedobuff();
did_filetype = FALSE;
+ while (au_pending_free_buf != NULL) {
+ buf_T *b = au_pending_free_buf->b_next;
+ vim_free(au_pending_free_buf);
+ au_pending_free_buf = b;
+ }
}
/*
diff --git a/src/globals.h b/src/globals.h
index 731c99623c..2b39ef5416 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -352,6 +352,11 @@ EXTERN int keep_filetype INIT(= FALSE); /* value for did_filetype when
* which one is preferred, au_new_curbuf is set to it */
EXTERN buf_T *au_new_curbuf INIT(= NULL);
+// When deleting the buffer and autocmd_busy is TRUE, do not free the buffer
+// but link it in the list starting with au_pending_free_buf, using b_next.
+// Free the buffer when autocmd_busy is set to FALSE.
+EXTERN buf_T *au_pending_free_buf INIT(= NULL);
+
/*
* Mouse coordinates, set by check_termcode()
*/
diff --git a/src/version.c b/src/version.c
index 72cc8cf5d4..0f00231659 100644
--- a/src/version.c
+++ b/src/version.c
@@ -209,7 +209,7 @@ static int included_patches[] = {
//254,
//253,
//252,
- //251,
+ 251,
//250,
//249,
//248,