To: [email protected]
Subject: patch 5.4p.5
Fcc: outbox
From: Bram Moolenaar <[email protected]>
------------

Another nasty autocommand problem.  It appears more people are using
autocommands these days.  It requires a radical change to how autocommands are
executed.  But not right now.


Patch 5.4p.5
Problem:    When changing buffers in a BufDelete autocommand, there could be
           ml_line errors and/or a crash. (Schandl)  Was caused by deleting
           the current buffer.
Solution:   When the buffer to be deleted unexpectedly becomes the current
           buffer, don't delete it.
           Also added a check for this in test13.
Files:      src/buffer.c, src/testdir/test13.in, src/testdir/test13.ok


*** ../vim-5.4p/src/buffer.c    Mon Jul 19 11:08:56 1999
--- src/buffer.c        Tue Jul 20 13:17:13 1999
***************
*** 185,190 ****
--- 185,194 ----
     int           free_buf;
     int           del_buf;
 {
+ #ifdef AUTOCMD
+     int               is_curbuf;
+ #endif
+
     if (buf->b_nwindows > 0)
       --buf->b_nwindows;
     if (buf->b_nwindows == 0 && win != NULL)
***************
*** 218,226 ****
      * Free all things allocated for this buffer.
      * Also calls the "BufDelete" autocommands when del_buf is TRUE.
      */
     buf_freeall(buf, del_buf);
!     if (!buf_valid(buf))          /* autocommands may delete the buffer */
       return;

     /*
      * Remove the buffer from the list.
--- 222,242 ----
      * Free all things allocated for this buffer.
      * Also calls the "BufDelete" autocommands when del_buf is TRUE.
      */
+ #ifdef AUTOCMD
+     is_curbuf = (buf == curbuf);
+ #endif
     buf_freeall(buf, del_buf);
! #ifdef AUTOCMD
!     /*
!      * Autocommands may have deleted the buffer.
!      * It's possible that autocommands change curbuf to the one being deleted.
!      * This might cause curbuf to be deleted unexpectedly.  But in some cases
!      * it's OK to delete the curbuf, because a new one is obtained anyway.
!      * Therefore only return if curbuf changed to the deleted buffer.
!      */
!     if (!buf_valid(buf) || (buf == curbuf && !is_curbuf))
       return;
+ #endif

     /*
      * Remove the buffer from the list.
***************
*** 267,276 ****
 /*ARGSUSED*/
     void
 buf_freeall(buf, del_buf)
!     BUF           *buf;
!     int           del_buf;    /* buffer is going to be deleted */
 {
 #ifdef AUTOCMD
     apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, FALSE, buf);
     if (!buf_valid(buf))          /* autocommands may delete the buffer */
       return;
--- 283,294 ----
 /*ARGSUSED*/
     void
 buf_freeall(buf, del_buf)
!     BUF               *buf;
!     int               del_buf;        /* buffer is going to be deleted */
 {
 #ifdef AUTOCMD
+     int               is_curbuf = (buf == curbuf);
+
     apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, FALSE, buf);
     if (!buf_valid(buf))          /* autocommands may delete the buffer */
       return;
***************
*** 280,285 ****
--- 298,311 ----
       if (!buf_valid(buf))        /* autocommands may delete the buffer */
           return;
     }
+     /*
+      * It's possible that autocommands change curbuf to the one being deleted.
+      * This might cause curbuf to be deleted unexpectedly.  But in some cases
+      * it's OK to delete the curbuf, because a new one is obtained anyway.
+      * Therefore only return if curbuf changed to the deleted buffer.
+      */
+     if (buf == curbuf && !is_curbuf)
+       return;
 #endif
 #ifdef HAVE_TCL
     tcl_buffer_free(buf);
*** ../vim-5.4p/src/testdir/test13.in   Mon Jul 19 11:08:50 1999
--- src/testdir/test13.in       Tue Jul 20 13:31:27 1999
***************
*** 7,12 ****
--- 7,15 ----
 Also test deleting the buffer on a Unload event.  If this goes wrong there
 will be the ATTENTION prompt.

+ Also test changing buffers in a BufDel autocommand.  If this goes wrong there
+ are ml_line errors and/or a Crash.
+
 STARTTEST
 :/^start of testfile/,/^end of testfile/w! Xtestje1
 :/^start of testfile/,/^end of testfile/w! Xtestje2
***************
*** 36,41 ****
--- 39,51 ----
 :e Xtestje2
 :sp Xtestje1
 :e
+ :w >>test.out
+ :au!
+ :only
+ :e Xtestje1
+ :bdel Xtestje2 Xtestje3 test.out test13.in
+ :au BufDelete Xtestje1 buf Xtestje1
+ :bd
 :w >>test.out
 :!rm -rf Xtestje*
 :qa!
*** ../vim-5.4p/src/testdir/test13.ok   Mon Jul 19 11:08:50 1999
--- src/testdir/test13.ok       Tue Jul 20 13:35:40 1999
***************
*** 22,24 ****
--- 22,30 ----
       contents
       contents
 end of testfile
+ start of testfile
+ testje1
+       contents
+       contents
+       contents
+ end of testfile

--
hundred-and-one symptoms of being an internet addict:
174. You know what a listserv is.

--/-/---- Bram Moolenaar ---- [email protected] ---- [email protected] ---\-\--
 \ \    www.vim.org/iccf      www.moolenaar.net       www.vim.org    / /