diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2022-07-05 11:31:49 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-05 02:31:49 -0700 |
commit | d0835617facc98daf79318e26d41669bb2ce1a6b (patch) | |
tree | be959e03888b70a0c8410280d2dcd65a97c367db | |
parent | eb814bdca0bad2a68e111d59fae62f79b8dbeef1 (diff) | |
download | rneovim-d0835617facc98daf79318e26d41669bb2ce1a6b.tar.gz rneovim-d0835617facc98daf79318e26d41669bb2ce1a6b.tar.bz2 rneovim-d0835617facc98daf79318e26d41669bb2ce1a6b.zip |
fix(terminal): crash if TermClose deletes own buffer #19222
- Partially fixes #10386 except for the case where the alternate buffer
is the default, empty, first buffer created on startup. #vimlife
- TODO: port patches related to `can_unload_buffer`, maybe that fully
fixes #10386?
vim-patch:8.0.1732: crash when terminal API call deletes the buffer
-rw-r--r-- | src/nvim/buffer.c | 9 | ||||
-rw-r--r-- | src/nvim/testdir/test_autocmd.vim | 7 | ||||
-rw-r--r-- | test/functional/autocmd/termxx_spec.lua | 20 |
3 files changed, 32 insertions, 4 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 7bdb905dfa..411705cfa3 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -89,6 +89,7 @@ static char *msg_loclist = N_("[Location List]"); static char *msg_qflist = N_("[Quickfix List]"); static char *e_auabort = N_("E855: Autocommands caused command to abort"); +static char *e_buflocked = N_("E937: Attempt to delete a buffer that is in use"); // Number of times free_buffer() was called. static int buf_free_count = 0; @@ -438,7 +439,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i // Disallow deleting the buffer when it is locked (already being closed or // halfway a command that relies on it). Unloading is allowed. if (buf->b_locked > 0 && (del_buf || wipe_buf)) { - emsg(_("E937: Attempt to delete a buffer that is in use")); + emsg(_(e_buflocked)); return false; } @@ -529,7 +530,9 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i } if (buf->terminal) { + buf->b_locked++; terminal_close(&buf->terminal, -1); + buf->b_locked--; } // Always remove the buffer when there is no file name. @@ -1182,6 +1185,10 @@ int do_buffer(int action, int start, int dir, int count, int forceit) if (unload) { int forward; bufref_T bufref; + if (buf->b_locked) { + emsg(_(e_buflocked)); + return FAIL; + } set_bufref(&bufref, buf); // When unloading or deleting a buffer that's already unloaded and diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index 660801d575..fcef57e47a 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -169,7 +169,9 @@ func Test_autocmd_bufunload_avoiding_SEGV_01() exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!' augroup END - call assert_fails('edit bb.txt', 'E937:') + " Todo: check for E937 generated first + " call assert_fails('edit bb.txt', 'E937:') + call assert_fails('edit bb.txt', 'E517:') autocmd! test_autocmd_bufunload augroup! test_autocmd_bufunload @@ -540,7 +542,7 @@ func Test_three_windows() e Xtestje2 sp Xtestje1 call assert_fails('e', 'E937:') - call assert_equal('Xtestje2', expand('%')) + call assert_equal('Xtestje1', expand('%')) " Test changing buffers in a BufWipeout autocommand. If this goes wrong " there are ml_line errors and/or a Crash. @@ -563,7 +565,6 @@ func Test_three_windows() au! enew - bwipe! Xtestje1 call delete('Xtestje1') call delete('Xtestje2') call delete('Xtestje3') diff --git a/test/functional/autocmd/termxx_spec.lua b/test/functional/autocmd/termxx_spec.lua index c418a12faf..859c2ebf44 100644 --- a/test/functional/autocmd/termxx_spec.lua +++ b/test/functional/autocmd/termxx_spec.lua @@ -7,6 +7,8 @@ local eval, eq, neq, retry = helpers.eval, helpers.eq, helpers.neq, helpers.retry local ok = helpers.ok local feed = helpers.feed +local pcall_err = helpers.pcall_err +local assert_alive = helpers.assert_alive local iswin = helpers.iswin describe('autocmd TermClose', function() @@ -16,6 +18,24 @@ describe('autocmd TermClose', function() command('set shellcmdflag=EXE shellredir= shellpipe= shellquote= shellxquote=') end) + + local function test_termclose_delete_own_buf() + command('autocmd TermClose * bdelete!') + command('terminal') + eq('Vim(bdelete):E937: Attempt to delete a buffer that is in use', pcall_err(command, 'bdelete!')) + assert_alive() + end + + -- TODO: fixed after merging patches for `can_unload_buffer`? + pending('TermClose deleting its own buffer, altbuf = buffer 1 #10386', function() + test_termclose_delete_own_buf() + end) + + it('TermClose deleting its own buffer, altbuf NOT buffer 1 #10386', function() + command('edit foo1') + test_termclose_delete_own_buf() + end) + it('triggers when fast-exiting terminal job stops', function() command('autocmd TermClose * let g:test_termclose = 23') command('terminal') |