summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-08-13 14:13:19 +0200
committerBram Moolenaar <Bram@vim.org>2017-08-13 14:13:19 +0200
commit679653e59c6da7f6abc29470ef9d404582bacbb9 (patch)
tree8a4dc65c4d861d43dc376c4f844755545ee1d8f3
parent55b6926450d75788dada3ff44a35e328224df758 (diff)
patch 8.0.0923: crash in GUI when terminal job exitsv8.0.0923
Problem: Crash in GUI when terminal job exits. (Kazunobu Kuriyama) Solution: reset in_terminal_loop when a terminal is freed.
-rw-r--r--src/terminal.c17
-rw-r--r--src/testdir/test_terminal.vim20
-rw-r--r--src/version.c2
3 files changed, 38 insertions, 1 deletions
diff --git a/src/terminal.c b/src/terminal.c
index 6d01a299c3..317615cfd8 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -34,9 +34,10 @@
*
* When the job ends the text is put in a buffer. Redrawing then happens from
* that buffer, attributes come from the scrollback buffer tl_scrollback.
+ * When the buffer is changed it is turned into a normal buffer, the attributes
+ * in tl_scrollback are no longer used.
*
* TODO:
- * - cursor shape/color/blink in the GUI
* - Make argument list work on MS-Windows. #1954
* - MS-Windows: no redraw for 'updatetime' #1915
* - To set BS correctly, check get_stty(); Pass the fd of the pty.
@@ -524,6 +525,8 @@ free_terminal(buf_T *buf)
vim_free(term->tl_cursor_color);
vim_free(term);
buf->b_term = NULL;
+ if (in_terminal_loop == term)
+ in_terminal_loop = NULL;
}
/*
@@ -1014,6 +1017,8 @@ term_enter_job_mode()
/*
* Get a key from the user without mapping.
+ * Note: while waiting a terminal may be closed and freed if the channel is
+ * closed and ++close was used.
* TODO: use terminal mode mappings.
*/
static int
@@ -1140,10 +1145,16 @@ term_paste_register(int prev_c UNUSED)
#ifdef FEAT_CMDL_INFO
clear_showcmd();
#endif
+ if (!term_use_loop())
+ /* job finished while waiting for a character */
+ return;
/* CTRL-W "= prompt for expression to evaluate. */
if (c == '=' && get_expr_register() != '=')
return;
+ if (!term_use_loop())
+ /* job finished while waiting for a character */
+ return;
l = (list_T *)get_reg_contents(c, GREG_LIST);
if (l != NULL)
@@ -1272,6 +1283,10 @@ terminal_loop(void)
int termkey = 0;
int ret;
+ /* Remember the terminal we are sending keys to. However, the terminal
+ * might be closed while waiting for a character, e.g. typing "exit" in a
+ * shell and ++close was used. Therefore use curbuf->b_term instead of a
+ * stored reference. */
in_terminal_loop = curbuf->b_term;
if (*curwin->w_p_tk != NUL)
diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim
index 4de853a6ab..3ca638af30 100644
--- a/src/testdir/test_terminal.vim
+++ b/src/testdir/test_terminal.vim
@@ -414,3 +414,23 @@ func Test_terminal_env()
exe buf . 'bwipe'
endfunc
+
+" must be last, we can't go back from GUI to terminal
+func Test_zz_terminal_in_gui()
+ if !has('gui')
+ return
+ endif
+ gui -f
+
+ call assert_equal(1, winnr('$'))
+ let buf = Run_shell_in_terminal({'term_finish': 'close'})
+ call Stop_shell_in_terminal(buf)
+ call term_wait(buf)
+
+ " closing window wipes out the terminal buffer a with finished job
+ call WaitFor("winnr('$') == 1")
+ call assert_equal(1, winnr('$'))
+ call assert_equal("", bufname(buf))
+
+ unlet g:job
+endfunc
diff --git a/src/version.c b/src/version.c
index 2200bf091a..3833f586ee 100644
--- a/src/version.c
+++ b/src/version.c
@@ -770,6 +770,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 923,
+/**/
922,
/**/
921,