Patch 8.0.0728
Problem:    The terminal structure is never freed.
Solution:   Free the structure and unreference what it contains.
Files:      src/terminal.c, src/buffer.c, src/proto/terminal.pro,
            src/channel.c, src/proto/channel.pro, src/evalfunc.c


*** ../vim-8.0.0727/src/terminal.c      2017-07-16 20:13:22.265843572 +0200
--- src/terminal.c      2017-07-17 23:02:01.568182115 +0200
***************
*** 25,35 ****
   *
   * 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.
   * - 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 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?
--- 25,34 ----
   *
   * TODO:
   * - pressing Enter sends two CR and/or NL characters to "bash -i"?
!  *   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 [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?
***************
*** 43,55 ****
   * - 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 'termkey'
   */
  
--- 42,55 ----
   * - support minimal size when 'termsize' is "rows*cols".
   * - support minimal size when 'termsize' is empty.
   * - implement ":buf {term-buf-name}"
!  * - 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,171 ****
      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;
--- 165,170 ----
***************
*** 185,195 ****
  
      term->tl_job = job_start(argvars, &opt);
  
!     /* TODO: setup channel to job */
      /* Setup pty, see mch_call_shell(). */
  }
  
  /*
   * Invoked when "msg" output from a job was received.  Write it to the 
terminal
   * of "buffer".
   */
--- 184,230 ----
  
      term->tl_job = job_start(argvars, &opt);
  
!     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,346 ****
--- 375,386 ----
                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;
*** ../vim-8.0.0727/src/buffer.c        2017-06-19 20:35:28.423401990 +0200
--- src/buffer.c        2017-07-17 22:43:49.212491624 +0200
***************
*** 859,864 ****
--- 859,867 ----
  #ifdef FEAT_JOB_CHANNEL
      channel_buffer_free(buf);
  #endif
+ #ifdef FEAT_TERMINAL
+     free_terminal(buf->b_term);
+ #endif
  
      buf_hashtab_remove(buf);
  
***************
*** 1771,1777 ****
  #endif
  
  #ifdef FEAT_SYN_HL
!     curwin->w_s = &(buf->b_s);
  #endif
  
      /* Cursor on first line by default. */
--- 1774,1780 ----
  #endif
  
  #ifdef FEAT_SYN_HL
!     curwin->w_s = &(curbuf->b_s);
  #endif
  
      /* Cursor on first line by default. */
*** ../vim-8.0.0727/src/proto/terminal.pro      2017-07-16 20:13:22.265843572 
+0200
--- src/proto/terminal.pro      2017-07-17 22:42:52.028931333 +0200
***************
*** 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);
*** ../vim-8.0.0727/src/channel.c       2017-07-16 14:04:24.974836858 +0200
--- src/channel.c       2017-07-17 22:42:41.625011343 +0200
***************
*** 4893,4899 ****
  }
  
  /*
!  * "job_start()" function
   */
      job_T *
  job_start(typval_T *argvars, jobopt_T *opt_arg)
--- 4893,4901 ----
  }
  
  /*
!  * 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,5160 ****
      dict_add_nr_str(dict, "stoponexit", 0L, job->jv_stoponexit);
  }
  
      int
! job_stop(job_T *job, typval_T *argvars)
  {
      char_u *arg;
  
!     if (argvars[1].v_type == VAR_UNKNOWN)
        arg = (char_u *)"";
      else
      {
--- 5151,5169 ----
      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, char *type)
  {
      char_u *arg;
  
!     if (type != NULL)
!       arg = (char_u *)type;
!     else if (argvars[1].v_type == VAR_UNKNOWN)
        arg = (char_u *)"";
      else
      {
*** ../vim-8.0.0727/src/proto/channel.pro       2017-07-16 13:48:18.190107174 
+0200
--- src/proto/channel.pro       2017-07-17 22:42:44.712987595 +0200
***************
*** 67,71 ****
  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);
  /* vim: set ft=c : */
--- 67,71 ----
  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, char *type);
  /* vim: set ft=c : */
*** ../vim-8.0.0727/src/evalfunc.c      2017-07-16 13:48:18.194107145 +0200
--- src/evalfunc.c      2017-07-17 22:40:51.225860521 +0200
***************
*** 6772,6778 ****
      job_T     *job = get_job_arg(&argvars[0]);
  
      if (job != NULL)
!       rettv->vval.v_number = job_stop(job, argvars);
  }
  #endif
  
--- 6772,6778 ----
      job_T     *job = get_job_arg(&argvars[0]);
  
      if (job != NULL)
!       rettv->vval.v_number = job_stop(job, argvars, NULL);
  }
  #endif
  
*** ../vim-8.0.0727/src/version.c       2017-07-16 20:54:29.646786469 +0200
--- src/version.c       2017-07-17 23:18:35.328680407 +0200
***************
*** 771,772 ****
--- 771,774 ----
  {   /* Add new patch number below this line */
+ /**/
+     728,
  /**/

-- 
If Microsoft would build a car...
... Occasionally, executing a maneuver such as a left turn
would cause your car to shut down and refuse to restart, in
which case you would have to reinstall the engine.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui