comparison src/buffer.c @ 10106:58e6dd1d8be3 v7.4.2324

commit https://github.com/vim/vim/commit/e0ab94e7123ca7855f45919114d948ef2bc1e8c3 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Sep 4 19:50:54 2016 +0200 patch 7.4.2324 Problem: Crash when editing a new buffer and BufUnload autocommand wipes out the new buffer. (Norio Takagi) Solution: Don't allow wiping out this buffer. (partly by Hirohito Higashi) Move old style test13 into test_autocmd. Avoid ml_get error when editing a file.
author Christian Brabandt <cb@256bit.org>
date Sun, 04 Sep 2016 20:00:07 +0200
parents 7fc6103c6651
children 7cb49e98d582
comparison
equal deleted inserted replaced
10105:5aca505bbcfe 10106:58e6dd1d8be3
474 } 474 }
475 else if (buf->b_p_bh[0] == 'u') /* 'bufhidden' == "unload" */ 475 else if (buf->b_p_bh[0] == 'u') /* 'bufhidden' == "unload" */
476 unload_buf = TRUE; 476 unload_buf = TRUE;
477 #endif 477 #endif
478 478
479 /* Disallow deleting the buffer when it is locked (already being closed or
480 * halfway a command that relies on it). Unloading is allowed. */
481 if (buf->b_locked > 0 && (del_buf || wipe_buf))
482 {
483 EMSG(_("E937: Attempt to delete a buffer that is in use"));
484 return;
485 }
486
479 if (win != NULL 487 if (win != NULL
480 #ifdef FEAT_WINDOWS 488 #ifdef FEAT_WINDOWS
481 && win_valid_any_tab(win) /* in case autocommands closed the window */ 489 && win_valid_any_tab(win) /* in case autocommands closed the window */
482 #endif 490 #endif
483 ) 491 )
497 set_bufref(&bufref, buf); 505 set_bufref(&bufref, buf);
498 506
499 /* When the buffer is no longer in a window, trigger BufWinLeave */ 507 /* When the buffer is no longer in a window, trigger BufWinLeave */
500 if (buf->b_nwindows == 1) 508 if (buf->b_nwindows == 1)
501 { 509 {
502 buf->b_closing = TRUE; 510 ++buf->b_locked;
503 if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, 511 if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname,
504 FALSE, buf) 512 FALSE, buf)
505 && !bufref_valid(&bufref)) 513 && !bufref_valid(&bufref))
506 { 514 {
507 /* Autocommands deleted the buffer. */ 515 /* Autocommands deleted the buffer. */
508 aucmd_abort: 516 aucmd_abort:
509 EMSG(_(e_auabort)); 517 EMSG(_(e_auabort));
510 return; 518 return;
511 } 519 }
512 buf->b_closing = FALSE; 520 --buf->b_locked;
513 if (abort_if_last && one_window()) 521 if (abort_if_last && one_window())
514 /* Autocommands made this the only window. */ 522 /* Autocommands made this the only window. */
515 goto aucmd_abort; 523 goto aucmd_abort;
516 524
517 /* When the buffer becomes hidden, but is not unloaded, trigger 525 /* When the buffer becomes hidden, but is not unloaded, trigger
518 * BufHidden */ 526 * BufHidden */
519 if (!unload_buf) 527 if (!unload_buf)
520 { 528 {
521 buf->b_closing = TRUE; 529 ++buf->b_locked;
522 if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, 530 if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname,
523 FALSE, buf) 531 FALSE, buf)
524 && !bufref_valid(&bufref)) 532 && !bufref_valid(&bufref))
525 /* Autocommands deleted the buffer. */ 533 /* Autocommands deleted the buffer. */
526 goto aucmd_abort; 534 goto aucmd_abort;
527 buf->b_closing = FALSE; 535 --buf->b_locked;
528 if (abort_if_last && one_window()) 536 if (abort_if_last && one_window())
529 /* Autocommands made this the only window. */ 537 /* Autocommands made this the only window. */
530 goto aucmd_abort; 538 goto aucmd_abort;
531 } 539 }
532 # ifdef FEAT_EVAL 540 # ifdef FEAT_EVAL
683 win_T *the_curwin = curwin; 691 win_T *the_curwin = curwin;
684 tabpage_T *the_curtab = curtab; 692 tabpage_T *the_curtab = curtab;
685 # endif 693 # endif
686 694
687 /* Make sure the buffer isn't closed by autocommands. */ 695 /* Make sure the buffer isn't closed by autocommands. */
688 buf->b_closing = TRUE; 696 ++buf->b_locked;
689 set_bufref(&bufref, buf); 697 set_bufref(&bufref, buf);
690 if (buf->b_ml.ml_mfp != NULL) 698 if (buf->b_ml.ml_mfp != NULL)
691 { 699 {
692 if (apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, 700 if (apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname,
693 FALSE, buf) 701 FALSE, buf)
709 FALSE, buf) 717 FALSE, buf)
710 && !bufref_valid(&bufref)) 718 && !bufref_valid(&bufref))
711 /* autocommands deleted the buffer */ 719 /* autocommands deleted the buffer */
712 return; 720 return;
713 } 721 }
714 buf->b_closing = FALSE; 722 --buf->b_locked;
715 723
716 # ifdef FEAT_WINDOWS 724 # ifdef FEAT_WINDOWS
717 /* If the buffer was in curwin and the window has changed, go back to that 725 /* If the buffer was in curwin and the window has changed, go back to that
718 * window, if it still exists. This avoids that ":edit x" triggering a 726 * window, if it still exists. This avoids that ":edit x" triggering a
719 * "tabnext" BufUnload autocmd leaves a window behind without a buffer. */ 727 * "tabnext" BufUnload autocmd leaves a window behind without a buffer. */
1367 * (unless it's the only window). Repeat this so long as we end up in 1375 * (unless it's the only window). Repeat this so long as we end up in
1368 * a window with this buffer. 1376 * a window with this buffer.
1369 */ 1377 */
1370 while (buf == curbuf 1378 while (buf == curbuf
1371 # ifdef FEAT_AUTOCMD 1379 # ifdef FEAT_AUTOCMD
1372 && !(curwin->w_closing || curwin->w_buffer->b_closing) 1380 && !(curwin->w_closing || curwin->w_buffer->b_locked > 0)
1373 # endif 1381 # endif
1374 && (firstwin != lastwin || first_tabpage->tp_next != NULL)) 1382 && (firstwin != lastwin || first_tabpage->tp_next != NULL))
1375 { 1383 {
1376 if (win_close(curwin, FALSE) == FAIL) 1384 if (win_close(curwin, FALSE) == FAIL)
1377 break; 1385 break;
5098 : wp->w_width != Columns) 5106 : wp->w_width != Columns)
5099 || (had_tab > 0 && wp != firstwin) 5107 || (had_tab > 0 && wp != firstwin)
5100 #endif 5108 #endif
5101 ) && firstwin != lastwin 5109 ) && firstwin != lastwin
5102 #ifdef FEAT_AUTOCMD 5110 #ifdef FEAT_AUTOCMD
5103 && !(wp->w_closing || wp->w_buffer->b_closing) 5111 && !(wp->w_closing || wp->w_buffer->b_locked > 0)
5104 #endif 5112 #endif
5105 ) 5113 )
5106 { 5114 {
5107 win_close(wp, FALSE); 5115 win_close(wp, FALSE);
5108 #ifdef FEAT_AUTOCMD 5116 #ifdef FEAT_AUTOCMD