]> granicus.if.org Git - vim/commitdiff
patch 8.2.0004: get E685 and E931 if buffer reload is interrupted v8.2.0004
authorBram Moolenaar <Bram@vim.org>
Sat, 14 Dec 2019 15:18:15 +0000 (16:18 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 14 Dec 2019 15:18:15 +0000 (16:18 +0100)
Problem:    Get E685 and E931 if buffer reload is interrupted.
Solution:   Do not abort deleting a dummy buffer. (closes #5361)

src/buffer.c
src/ex_cmds.c
src/ex_getln.c
src/misc2.c
src/proto/buffer.pro
src/quickfix.c
src/testdir/test_trycatch.vim
src/version.c
src/vim.h
src/window.c

index b4992dda0747f4a50fa3e98ec372c304761bee3a..da10579cccbf202d2b0efc0dc24ee77b0e4c99d8 100644 (file)
@@ -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();
index 45c733bbae05939931c08a1aa3cea80b5f1f5375..49104919449190ddc6da333638baf8f0d6fb01ad 100644 (file)
@@ -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;
index 769dcb8363020ca3cef4ac98f5b42f38b03a4c8f..51433f1ec292a53b2d4a716330beefe0c2e92340 100644 (file)
@@ -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);
index 80731f02ae8300d14ce32ee85ea12c74ac4b09f3..ce767984fdaafe554e79504438c98ec0620db7f5 100644 (file)
@@ -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
index d876cd5378296a8e2e25a133fa0e10dd229ec84b..3a632993646db44baf7be17362b907ba5459dc6a 100644 (file)
@@ -5,7 +5,7 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags);
 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);
index 206e90165c5dec7fc5d4ef4914e1d210b0b7af38..2e07403a89e26fc89cad47d9c04564eef97ba5ce 100644 (file)
@@ -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 *dirname_start)
 {
     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);
index 7e513180a3cc82a588ee866687e8660dd4ff03d9..adc1745b3939b062c4de43edf8c8a30e72d66efb 100644 (file)
@@ -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
-"-------------------------------------------------------------------------------
index 19eaf451b5ce19b1254e75498f3227b2d9019eff..c979eeb9d8abf6846a6bdfaabd03c9b03f3be3ec 100644 (file)
@@ -742,6 +742,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4,
 /**/
     3,
 /**/
index 68e2de1dec9aa0bbb8480386afed54dab39292a6..a01d4b290858b347c06839cc24f337e1b687915e 100644 (file)
--- 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
index 5b407d5b6555bb1ca2d2a8e589e4604fda52dbe7..b66fb34febd5eec7da9583f24e4d053cef08807b 100644 (file)
@@ -2410,7 +2410,7 @@ win_close_buffer(win_T *win, int action, int abort_if_last)
 
        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_buf, tabpage_T *tp)
 
     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);