]> granicus.if.org Git - vim/commitdiff
patch 8.0.0728: the terminal structure is never freed v8.0.0728
authorBram Moolenaar <Bram@vim.org>
Mon, 17 Jul 2017 21:20:24 +0000 (23:20 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 17 Jul 2017 21:20:24 +0000 (23:20 +0200)
Problem:    The terminal structure is never freed.
Solution:   Free the structure and unreference what it contains.

src/buffer.c
src/channel.c
src/evalfunc.c
src/proto/channel.pro
src/proto/terminal.pro
src/terminal.c
src/version.c

index e8e1a6de0adab39594dcc48e45991857605b56db..dbd4d3ae96b51f0e93edbb6209ef272ccc8f2466 100644 (file)
@@ -859,6 +859,9 @@ free_buffer(buf_T *buf)
 #ifdef FEAT_JOB_CHANNEL
     channel_buffer_free(buf);
 #endif
+#ifdef FEAT_TERMINAL
+    free_terminal(buf->b_term);
+#endif
 
     buf_hashtab_remove(buf);
 
@@ -1771,7 +1774,7 @@ enter_buffer(buf_T *buf)
 #endif
 
 #ifdef FEAT_SYN_HL
-    curwin->w_s = &(buf->b_s);
+    curwin->w_s = &(curbuf->b_s);
 #endif
 
     /* Cursor on first line by default. */
index 939b51392ad0e5adc9bb176da377af7b5f1d1357..db3468353ecea03fe1eaf7fc7059176da688952c 100644 (file)
@@ -4893,7 +4893,9 @@ job_check_ended(void)
 }
 
 /*
- * "job_start()" function
+ * Create a job and return it.  Implements job_start().
+ * The returned job has a refcount of one.
+ * Returns NULL when out of memory.
  */
     job_T *
 job_start(typval_T *argvars, jobopt_T *opt_arg)
@@ -5149,12 +5151,19 @@ job_info(job_T *job, dict_T *dict)
     dict_add_nr_str(dict, "stoponexit", 0L, job->jv_stoponexit);
 }
 
+/*
+ * Send a signal to "job".  Implements job_stop().
+ * When "type" is not NULL use this for the type.
+ * Otherwise use argvars[1] for the type.
+ */
     int
-job_stop(job_T *job, typval_T *argvars)
+job_stop(job_T *job, typval_T *argvars, char *type)
 {
     char_u *arg;
 
-    if (argvars[1].v_type == VAR_UNKNOWN)
+    if (type != NULL)
+       arg = (char_u *)type;
+    else if (argvars[1].v_type == VAR_UNKNOWN)
        arg = (char_u *)"";
     else
     {
index 428d7a4c5b4c823028aad0bd9f7dc38b917ecfef..33307e5270425c348fa489952deaacddd78f6eb2 100644 (file)
@@ -6772,7 +6772,7 @@ f_job_stop(typval_T *argvars, typval_T *rettv)
     job_T      *job = get_job_arg(&argvars[0]);
 
     if (job != NULL)
-       rettv->vval.v_number = job_stop(job, argvars);
+       rettv->vval.v_number = job_stop(job, argvars, NULL);
 }
 #endif
 
index 6c845ca940e9f6ae36d6af3fed8cf7efe7a1f3d8..e576584c496afd938da92a3f261356d80a9cc855 100644 (file)
@@ -67,5 +67,5 @@ void job_check_ended(void);
 job_T *job_start(typval_T *argvars, jobopt_T *opt_arg);
 char *job_status(job_T *job);
 void job_info(job_T *job, dict_T *dict);
-int job_stop(job_T *job, typval_T *argvars);
+int job_stop(job_T *job, typval_T *argvars, char *type);
 /* vim: set ft=c : */
index e89b0a26a214d11a99d114dd64961ea27cb81f06..58eb77fb5fe7d82e1c9f4ccf0f881e14bb518347 100644 (file)
@@ -1,5 +1,6 @@
 /* terminal.c */
 void ex_terminal(exarg_T *eap);
+void free_terminal(term_T *term);
 void write_to_term(buf_T *buffer, char_u *msg, channel_T *channel);
 void term_update_window(win_T *wp);
 void terminal_loop(void);
index 63bc6abb1d4787d47aed374589763c6170ba28b0..9d1f35ff100ad9cab79590170cc65a19aed55a98 100644 (file)
  *
  * TODO:
  * - pressing Enter sends two CR and/or NL characters to "bash -i"?
- * - free b_term when closing terminal.
- * - remove term from first_term list when closing terminal.
+ *   Passing Enter as NL seems to work.
  * - set buffer options to be scratch, hidden, nomodifiable, etc.
  * - set buffer name to command, add (1) to avoid duplicates.
- * - if buffer is wiped, cleanup terminal, may stop job.
+ * - If [command] is not given the 'shell' option is used.
  * - if the job ends, write "-- JOB ENDED --" in the terminal
  * - when closing window and job ended, delete the terminal
  * - when closing window and job has not ended, make terminal hidden?
  * - support minimal size when 'termsize' is "rows*cols".
  * - support minimal size when 'termsize' is empty.
  * - implement ":buf {term-buf-name}"
- * - implement term_getsize()
- * - implement term_setsize()
- * - implement term_sendkeys()         send keystrokes to a terminal
- * - implement term_wait()             wait for screen to be updated
- * - implement term_scrape()           inspect terminal screen
- * - implement term_open()             open terminal window
- * - implement term_getjob()
+ * - implement term_list()                     list of buffers with a terminal
+ * - implement term_getsize(buf)
+ * - implement term_setsize(buf)
+ * - implement term_sendkeys(buf, keys)                send keystrokes to a terminal
+ * - implement term_wait(buf)                  wait for screen to be updated
+ * - implement term_scrape(buf, row)           inspect terminal screen
+ * - implement term_open(command, options)     open terminal window
+ * - implement term_getjob(buf)
  * - implement 'termkey'
  */
 
@@ -165,7 +165,6 @@ ex_terminal(exarg_T *eap)
     vterm_screen_reset(screen, 1 /* hard */);
 
     /* By default NL means CR-NL. */
-    /* TODO: this causes two prompts when using ":term bash -i". */
     vterm_input_write(vterm, "\x1b[20h", 5);
 
     argvars[0].v_type = VAR_STRING;
@@ -185,10 +184,46 @@ ex_terminal(exarg_T *eap)
 
     term->tl_job = job_start(argvars, &opt);
 
-    /* TODO: setup channel to job */
+    if (term->tl_job == NULL)
+       /* Wiping out the buffer will also close the window. */
+       do_buffer(DOBUF_WIPE, DOBUF_CURRENT, FORWARD, 0, TRUE);
+
     /* Setup pty, see mch_call_shell(). */
 }
 
+/*
+ * Free a terminal and everything it refers to.
+ * Kills the job if there is one.
+ * Called when wiping out a buffer.
+ */
+    void
+free_terminal(term_T *term)
+{
+    term_T     *tp;
+
+    if (term == NULL)
+       return;
+    if (first_term == term)
+       first_term = term->tl_next;
+    else
+       for (tp = first_term; tp->tl_next != NULL; tp = tp->tl_next)
+           if (tp->tl_next == term)
+           {
+               tp->tl_next = term->tl_next;
+               break;
+           }
+
+    if (term->tl_job != NULL)
+    {
+       if (term->tl_job->jv_status != JOB_ENDED)
+           job_stop(term->tl_job, NULL, "kill");
+       job_unref(term->tl_job);
+    }
+
+    vterm_free(term->tl_vterm);
+    vim_free(term);
+}
+
 /*
  * Invoked when "msg" output from a job was received.  Write it to the terminal
  * of "buffer".
@@ -340,7 +375,12 @@ terminal_loop(void)
                stuffcharReadbuff(Ctrl_W);
                return;
 
+           /* TODO: which of these two should be used? */
+#if 0
            case CAR:           key = VTERM_KEY_ENTER; break;
+#else
+           case CAR:           c = NL; break;
+#endif
            case ESC:           key = VTERM_KEY_ESCAPE; break;
            case K_BS:          key = VTERM_KEY_BACKSPACE; break;
            case K_DEL:         key = VTERM_KEY_DEL; break;
index 77ff8c773d6cb6b2c44746910b87ab4c80be284b..41b0690ef3f76fa30a8d0fdc382edf4018306bac 100644 (file)
@@ -769,6 +769,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    728,
 /**/
     727,
 /**/