forked from aniani/vim
patch 8.0.1732: crash when terminal API call deletes the buffer
Problem: Crash when terminal API call deletes the buffer. Solution: Lock the buffer while calling a function. (closes #2813)
This commit is contained in:
parent
e87edf3b85
commit
a997b45c7e
17
src/buffer.c
17
src/buffer.c
@ -417,6 +417,8 @@ buf_hashtab_remove(buf_T *buf)
|
||||
hash_remove(&buf_hashtab, hi);
|
||||
}
|
||||
|
||||
static char *e_buflocked = N_("E937: Attempt to delete a buffer that is in use");
|
||||
|
||||
/*
|
||||
* Close the link to a buffer.
|
||||
* "action" is used when there is no longer a window for the buffer.
|
||||
@ -476,8 +478,15 @@ close_buffer(
|
||||
if (term_job_running(buf->b_term))
|
||||
{
|
||||
if (wipe_buf || unload_buf)
|
||||
{
|
||||
if (buf->b_locked)
|
||||
{
|
||||
EMSG(_(e_buflocked));
|
||||
return;
|
||||
}
|
||||
/* Wiping out or unloading a terminal buffer kills the job. */
|
||||
free_terminal(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The job keeps running, hide the buffer. */
|
||||
@ -499,7 +508,7 @@ close_buffer(
|
||||
* 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;
|
||||
}
|
||||
|
||||
@ -1356,6 +1365,12 @@ do_buffer(
|
||||
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
|
||||
|
@ -46,6 +46,9 @@
|
||||
* switch to GUI, shell stops working. Scrollback seems wrong, command
|
||||
* running in shell is still running.
|
||||
* - GUI: when using tabs, focus in terminal, click on tab does not work.
|
||||
* - handle_moverect() scrolls one line at a time. Postpone scrolling, count
|
||||
* the number of lines, until a redraw happens. Then if scrolling many lines
|
||||
* a redraw is faster.
|
||||
* - Copy text in the vterm to the Vim buffer once in a while, so that
|
||||
* completion works.
|
||||
* - Redrawing is slow with Athena and Motif. Also other GUI? (Ramel Eshed)
|
||||
@ -3433,6 +3436,10 @@ parse_osc(const char *command, size_t cmdlen, void *user)
|
||||
{
|
||||
char_u *cmd = get_tv_string(&item->li_tv);
|
||||
|
||||
/* Make sure an invoked command doesn't delete the buffer (and the
|
||||
* terminal) under our fingers. */
|
||||
++term->tl_buffer->b_locked;
|
||||
|
||||
item = item->li_next;
|
||||
if (item == NULL)
|
||||
ch_log(channel, "Missing argument for %s", cmd);
|
||||
@ -3442,6 +3449,7 @@ parse_osc(const char *command, size_t cmdlen, void *user)
|
||||
handle_call_command(term, channel, item);
|
||||
else
|
||||
ch_log(channel, "Invalid command received: %s", cmd);
|
||||
--term->tl_buffer->b_locked;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -119,7 +119,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
|
||||
@ -316,7 +318,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.
|
||||
@ -338,7 +340,6 @@ func Test_three_windows()
|
||||
|
||||
au!
|
||||
enew
|
||||
bwipe! Xtestje1
|
||||
call delete('Xtestje1')
|
||||
call delete('Xtestje2')
|
||||
call delete('Xtestje3')
|
||||
@ -1181,7 +1182,9 @@ endfunc
|
||||
func Test_nocatch_wipe_all_buffers()
|
||||
" Real nasty autocommand: wipe all buffers on any event.
|
||||
au * * bwipe *
|
||||
call assert_fails('next x', 'E93')
|
||||
" Get E93 first?
|
||||
" call assert_fails('next x', 'E93:')
|
||||
call assert_fails('next x', 'E517:')
|
||||
bwipe
|
||||
au!
|
||||
endfunc
|
||||
|
@ -1287,6 +1287,30 @@ func Test_terminal_api_call_fails()
|
||||
call delete('Xlog')
|
||||
endfunc
|
||||
|
||||
let s:caught_e937 = 0
|
||||
|
||||
func Tapi_Delete(bufnum, arg)
|
||||
try
|
||||
execute 'bdelete!' a:bufnum
|
||||
catch /E937:/
|
||||
let s:caught_e937 = 1
|
||||
endtry
|
||||
endfunc
|
||||
|
||||
func Test_terminal_api_call_fail_delete()
|
||||
if !CanRunVimInTerminal()
|
||||
return
|
||||
endif
|
||||
|
||||
call WriteApiCall('Tapi_Delete')
|
||||
let buf = RunVimInTerminal('-S Xscript', {})
|
||||
call WaitFor({-> s:caught_e937 == 1})
|
||||
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('Xscript')
|
||||
call ch_logfile('', '')
|
||||
endfunc
|
||||
|
||||
func Test_terminal_ansicolors_default()
|
||||
let colors = [
|
||||
\ '#000000', '#e00000',
|
||||
|
@ -762,6 +762,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1732,
|
||||
/**/
|
||||
1731,
|
||||
/**/
|
||||
|
Loading…
x
Reference in New Issue
Block a user