# HG changeset patch # User Bram Moolenaar # Date 1576337404 -3600 # Node ID 050f5eaa9e50c73ad5d1ad96dc166e9d0c42ea13 # Parent f4852c310de106f91db40732ab0e8d9b279c4ed6 patch 8.2.0004: get E685 and E931 if buffer reload is interrupted Commit: https://github.com/vim/vim/commit/a6e8f888e7fc31b8ab7233509254fb2e2fe4089f Author: Bram Moolenaar Date: Sat Dec 14 16:18:15 2019 +0100 patch 8.2.0004: get E685 and E931 if buffer reload is interrupted Problem: Get E685 and E931 if buffer reload is interrupted. Solution: Do not abort deleting a dummy buffer. (closes https://github.com/vim/vim/issues/5361) diff --git a/src/buffer.c b/src/buffer.c --- a/src/buffer.c +++ b/src/buffer.c @@ -184,7 +184,7 @@ open_buffer( * There MUST be a memfile, otherwise we can't do anything * If we can't create one for the current buffer, take another buffer */ - close_buffer(NULL, curbuf, 0, FALSE); + close_buffer(NULL, curbuf, 0, FALSE, FALSE); FOR_ALL_BUFFERS(curbuf) if (curbuf->b_ml.ml_mfp != NULL) break; @@ -487,13 +487,16 @@ can_unload_buffer(buf_T *buf) * When "abort_if_last" is TRUE then do not close the buffer if autocommands * cause there to be only one window with this buffer. e.g. when ":quit" is * supposed to close the window but autocommands close all other windows. + * + * When "ignore_abort" is TRUE don't abort even when aborting() returns TRUE. */ void close_buffer( win_T *win, // if not NULL, set b_last_cursor buf_T *buf, int action, - int abort_if_last) + int abort_if_last, + int ignore_abort) { int is_curbuf; int nwindows; @@ -609,7 +612,8 @@ aucmd_abort: goto aucmd_abort; } #ifdef FEAT_EVAL - if (aborting()) // autocmds may abort script processing + // autocmds may abort script processing + if (!ignore_abort && aborting()) return; #endif } @@ -662,13 +666,16 @@ aucmd_abort: is_curbuf = (buf == curbuf); buf->b_nwindows = nwindows; - buf_freeall(buf, (del_buf ? BFA_DEL : 0) + (wipe_buf ? BFA_WIPE : 0)); + buf_freeall(buf, (del_buf ? BFA_DEL : 0) + + (wipe_buf ? BFA_WIPE : 0) + + (ignore_abort ? BFA_IGNORE_ABORT : 0)); // Autocommands may have deleted the buffer. if (!bufref_valid(&bufref)) return; #ifdef FEAT_EVAL - if (aborting()) // autocmds may abort script processing + // autocmds may abort script processing + if (!ignore_abort && aborting()) return; #endif @@ -762,9 +769,10 @@ buf_clear_file(buf_T *buf) * buf_freeall() - free all things allocated for a buffer that are related to * the file. Careful: get here with "curwin" NULL when exiting. * flags: - * BFA_DEL buffer is going to be deleted - * BFA_WIPE buffer is going to be wiped out - * BFA_KEEP_UNDO do not free undo information + * BFA_DEL buffer is going to be deleted + * BFA_WIPE buffer is going to be wiped out + * BFA_KEEP_UNDO do not free undo information + * BFA_IGNORE_ABORT don't abort even when aborting() returns TRUE */ void buf_freeall(buf_T *buf, int flags) @@ -815,7 +823,8 @@ buf_freeall(buf_T *buf, int flags) } #ifdef FEAT_EVAL - if (aborting()) // autocmds may abort script processing + // autocmds may abort script processing + if ((flags & BFA_IGNORE_ABORT) == 0 && aborting()) return; #endif @@ -1077,7 +1086,7 @@ handle_swap_exists(bufref_T *old_curbuf) // open a new, empty buffer. swap_exists_action = SEA_NONE; // don't want it again swap_exists_did_quit = TRUE; - close_buffer(curwin, curbuf, DOBUF_UNLOAD, FALSE); + close_buffer(curwin, curbuf, DOBUF_UNLOAD, FALSE, FALSE); if (old_curbuf == NULL || !bufref_valid(old_curbuf) || old_curbuf->br_buf == curbuf) buf = buflist_new(NULL, NULL, 1L, BLN_CURBUF | BLN_LISTED); @@ -1281,7 +1290,7 @@ empty_curbuf( * if the buffer still exists. */ if (buf != curbuf && bufref_valid(&bufref) && buf->b_nwindows == 0) - close_buffer(NULL, buf, action, FALSE); + close_buffer(NULL, buf, action, FALSE, FALSE); if (!close_others) need_fileinfo = FALSE; return retval; @@ -1478,7 +1487,7 @@ do_buffer( { close_windows(buf, FALSE); if (buf != curbuf && bufref_valid(&bufref) && buf->b_nwindows <= 0) - close_buffer(NULL, buf, action, FALSE); + close_buffer(NULL, buf, action, FALSE, FALSE); return OK; } @@ -1708,7 +1717,8 @@ set_curbuf(buf_T *buf, int action) close_buffer(prevbuf == curwin->w_buffer ? curwin : NULL, prevbuf, unload ? action : (action == DOBUF_GOTO && !buf_hide(prevbuf) - && !bufIsChanged(prevbuf)) ? DOBUF_UNLOAD : 0, FALSE); + && !bufIsChanged(prevbuf)) ? DOBUF_UNLOAD : 0, + FALSE, FALSE); if (curwin != previouswin && win_valid(previouswin)) // autocommands changed curwin, Grr! curwin = previouswin; @@ -3296,7 +3306,7 @@ setfname( return FAIL; } // delete from the list - close_buffer(NULL, obuf, DOBUF_WIPE, FALSE); + close_buffer(NULL, obuf, DOBUF_WIPE, FALSE, FALSE); } sfname = vim_strsave(sfname); if (ffname == NULL || sfname == NULL) @@ -5633,7 +5643,7 @@ buf_contents_changed(buf_T *buf) void wipe_buffer( buf_T *buf, - int aucmd UNUSED) // When TRUE trigger autocommands. + int aucmd) // When TRUE trigger autocommands. { if (buf->b_fnum == top_file_num - 1) --top_file_num; @@ -5641,7 +5651,7 @@ wipe_buffer( if (!aucmd) // Don't trigger BufDelete autocommands here. block_autocmds(); - close_buffer(NULL, buf, DOBUF_WIPE, FALSE); + close_buffer(NULL, buf, DOBUF_WIPE, FALSE, TRUE); if (!aucmd) unblock_autocmds(); diff --git a/src/ex_cmds.c b/src/ex_cmds.c --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -2742,7 +2742,7 @@ do_ecmd( // oldwin->w_buffer to NULL. u_sync(FALSE); close_buffer(oldwin, curbuf, - (flags & ECMD_HIDE) ? 0 : DOBUF_UNLOAD, FALSE); + (flags & ECMD_HIDE) ? 0 : DOBUF_UNLOAD, FALSE, FALSE); the_curwin->w_closing = FALSE; --buf->b_locked; diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -4372,7 +4372,7 @@ open_cmdwin(void) // win_close() may have already wiped the buffer when 'bh' is // set to 'wipe' if (bufref_valid(&bufref)) - close_buffer(NULL, bufref.br_buf, DOBUF_WIPE, FALSE); + close_buffer(NULL, bufref.br_buf, DOBUF_WIPE, FALSE, FALSE); // Restore window sizes. win_size_restore(&winsizes); diff --git a/src/misc2.c b/src/misc2.c --- a/src/misc2.c +++ b/src/misc2.c @@ -1185,7 +1185,7 @@ free_all_mem(void) set_bufref(&bufref, buf); nextbuf = buf->b_next; - close_buffer(NULL, buf, DOBUF_WIPE, FALSE); + close_buffer(NULL, buf, DOBUF_WIPE, FALSE, FALSE); if (bufref_valid(&bufref)) buf = nextbuf; /* didn't work, try next one */ else diff --git a/src/proto/buffer.pro b/src/proto/buffer.pro --- a/src/proto/buffer.pro +++ b/src/proto/buffer.pro @@ -5,7 +5,7 @@ int open_buffer(int read_stdin, exarg_T void set_bufref(bufref_T *bufref, buf_T *buf); int bufref_valid(bufref_T *bufref); int buf_valid(buf_T *buf); -void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last); +void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last, int ignore_abort); void buf_clear_file(buf_T *buf); void buf_freeall(buf_T *buf, int flags); void goto_buffer(exarg_T *eap, int start, int dir, int count); diff --git a/src/quickfix.c b/src/quickfix.c --- a/src/quickfix.c +++ b/src/quickfix.c @@ -1925,7 +1925,7 @@ wipe_qf_buffer(qf_info_T *qi) { // If the quickfix buffer is not loaded in any window, then // wipe the buffer. - close_buffer(NULL, qfbuf, DOBUF_WIPE, FALSE); + close_buffer(NULL, qfbuf, DOBUF_WIPE, FALSE, FALSE); qi->qf_bufnr = INVALID_QFBUFNR; } } @@ -6311,7 +6311,7 @@ unload_dummy_buffer(buf_T *buf, char_u * { if (curbuf != buf) // safety check { - close_buffer(NULL, buf, DOBUF_UNLOAD, FALSE); + close_buffer(NULL, buf, DOBUF_UNLOAD, FALSE, TRUE); // When autocommands/'autochdir' option changed directory: go back. restore_start_dir(dirname_start); diff --git a/src/testdir/test_trycatch.vim b/src/testdir/test_trycatch.vim --- a/src/testdir/test_trycatch.vim +++ b/src/testdir/test_trycatch.vim @@ -1972,6 +1972,29 @@ func Test_builtin_func_error() call assert_equal('jlmnpqrtueghivyzACD', g:Xpath) endfunc -" Modelines {{{1 +func Test_reload_in_try_catch() + call writefile(['x'], 'Xreload') + set autoread + edit Xreload + tabnew + call writefile(['xx'], 'Xreload') + augroup ReLoad + au FileReadPost Xreload let x = doesnotexist + au BufReadPost Xreload let x = doesnotexist + augroup END + try + edit Xreload + catch + endtry + tabnew + + tabclose + tabclose + autocmd! ReLoad + set noautoread + bwipe! Xreload + call delete('Xreload') +endfunc + +" Modeline {{{1 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker -"------------------------------------------------------------------------------- diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -743,6 +743,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4, +/**/ 3, /**/ 2, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -2458,9 +2458,10 @@ typedef enum { #define VIF_GET_OLDFILES 8 // load v:oldfiles // flags for buf_freeall() -#define BFA_DEL 1 // buffer is going to be deleted -#define BFA_WIPE 2 // buffer is going to be wiped out -#define BFA_KEEP_UNDO 4 // do not free undo information +#define BFA_DEL 1 // buffer is going to be deleted +#define BFA_WIPE 2 // buffer is going to be wiped out +#define BFA_KEEP_UNDO 4 // do not free undo information +#define BFA_IGNORE_ABORT 8 // do not abort for aborting() // direction for nv_mousescroll() and ins_mousescroll() #define MSCR_DOWN 0 // DOWN must be FALSE diff --git a/src/window.c b/src/window.c --- a/src/window.c +++ b/src/window.c @@ -2410,7 +2410,7 @@ win_close_buffer(win_T *win, int action, set_bufref(&bufref, curbuf); win->w_closing = TRUE; - close_buffer(win, win->w_buffer, action, abort_if_last); + close_buffer(win, win->w_buffer, action, abort_if_last, FALSE); if (win_valid_any_tab(win)) win->w_closing = FALSE; // Make sure curbuf is valid. It can become invalid if 'bufhidden' is @@ -2677,7 +2677,8 @@ win_close_othertab(win_T *win, int free_ if (win->w_buffer != NULL) // Close the link to the buffer. - close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, FALSE); + close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, + FALSE, FALSE); // Careful: Autocommands may have closed the tab page or made it the // current tab page. @@ -5001,7 +5002,7 @@ win_free_popup(win_T *win) if (bt_popup(win->w_buffer)) win_close_buffer(win, DOBUF_WIPE_REUSE, FALSE); else - close_buffer(win, win->w_buffer, 0, FALSE); + close_buffer(win, win->w_buffer, 0, FALSE, FALSE); # if defined(FEAT_TIMERS) if (win->w_popup_timer != NULL) stop_timer(win->w_popup_timer);