Mercurial > vim
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 |