Patch 8.0.0050
Problem:    An exiting job is detected with a large latency.
Solution:   Check for pending job more often. (Ozaki Kiichi)  Change the
            double loop in mch_inchar() into one.
Files:      src/channel.c, src/os_unix.c, src/testdir/shared.vim,
            src/testdir/test_channel.vim


*** ../vim-8.0.0049/src/channel.c       2016-10-15 18:36:45.341910365 +0200
--- src/channel.c       2016-10-27 19:49:15.597305647 +0200
***************
*** 4643,4650 ****
  }
  
  /*
!  * Return TRUE when there is any job that might exit, which means
!  * job_check_ended() should be called once in a while.
   */
      int
  has_pending_job(void)
--- 4643,4650 ----
  }
  
  /*
!  * Return TRUE when there is any job that has an exit callback and might exit,
!  * which means job_check_ended() should be called more often.
   */
      int
  has_pending_job(void)
***************
*** 4652,4658 ****
      job_T         *job;
  
      for (job = first_job; job != NULL; job = job->jv_next)
!       if (job_still_alive(job))
            return TRUE;
      return FALSE;
  }
--- 4652,4662 ----
      job_T         *job;
  
      for (job = first_job; job != NULL; job = job->jv_next)
!       /* Only should check if the channel has been closed, if the channel is
!        * open the job won't exit. */
!       if (job->jv_status == JOB_STARTED && job->jv_exit_cb != NULL
!               && (job->jv_channel == NULL
!                   || !channel_still_useful(job->jv_channel)))
            return TRUE;
      return FALSE;
  }
*** ../vim-8.0.0049/src/os_unix.c       2016-10-18 16:27:20.544756017 +0200
--- src/os_unix.c       2016-10-27 19:43:31.019404929 +0200
***************
*** 404,542 ****
  {
      int               len;
      int               interrupted = FALSE;
      long      wait_time;
  #if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
      struct timeval  start_tv;
  
      gettimeofday(&start_tv, NULL);
  #endif
  
! #ifdef MESSAGE_QUEUE
!     parse_queued_messages();
! #endif
! 
!     /* Check if window changed size while we were busy, perhaps the ":set
!      * columns=99" command was used. */
!     while (do_resize)
!       handle_resize();
! 
      for (;;)
      {
!       if (wtime >= 0)
!           wait_time = wtime;
!       else
!           wait_time = p_ut;
! #if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
!       wait_time -= elapsed(&start_tv);
!       if (wait_time >= 0)
!       {
! #endif
!           if (WaitForChar(wait_time, &interrupted))
!               break;
  
-           /* no character available */
-           if (do_resize)
-           {
-               handle_resize();
-               continue;
-           }
- #ifdef FEAT_CLIENTSERVER
-           if (server_waiting())
-           {
-               parse_queued_messages();
-               continue;
-           }
- #endif
  #ifdef MESSAGE_QUEUE
!           if (interrupted)
!           {
!               parse_queued_messages();
!               continue;
!           }
  #endif
  #if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
!       }
  #endif
!       if (wtime >= 0)
!           /* no character available within "wtime" */
!           return 0;
! 
!       /* wtime == -1: no character available within 'updatetime' */
  #ifdef FEAT_AUTOCMD
!       if (trigger_cursorhold() && maxlen >= 3
!                                          && !typebuf_changed(tb_change_cnt))
!       {
!           buf[0] = K_SPECIAL;
!           buf[1] = KS_EXTRA;
!           buf[2] = (int)KE_CURSORHOLD;
!           return 3;
        }
- #endif
-       /*
-        * If there is no character available within 'updatetime' seconds
-        * flush all the swap files to disk.
-        * Also done when interrupted by SIGWINCH.
-        */
-       before_blocking();
-       break;
-     }
- 
-     /* repeat until we got a character */
-     for (;;)
-     {
-       long    wtime_now = -1L;
- 
-       while (do_resize)    /* window changed size */
-           handle_resize();
- 
- #ifdef MESSAGE_QUEUE
-       parse_queued_messages();
  
! # ifdef FEAT_JOB_CHANNEL
!       if (has_pending_job())
!       {
!           /* Don't wait longer than a few seconds, checking for a finished
!            * job requires polling. */
!           if (p_ut > 9000L)
!               wtime_now = 1000L;
!           else
!               wtime_now = 10000L - p_ut;
!       }
! # endif
  #endif
        /*
         * We want to be interrupted by the winch signal
         * or by an event on the monitored file descriptors.
         */
!       if (!WaitForChar(wtime_now, &interrupted))
        {
!           if (do_resize)          /* interrupted by SIGWINCH signal */
!               continue;
! #ifdef MESSAGE_QUEUE
!           if (interrupted || wtime_now > 0)
!           {
!               parse_queued_messages();
!               continue;
!           }
! #endif
!           return 0;
        }
  
!       /* If input was put directly in typeahead buffer bail out here. */
!       if (typebuf_changed(tb_change_cnt))
!           return 0;
  
!       /*
!        * For some terminals we only get one character at a time.
!        * We want the get all available characters, so we could keep on
!        * trying until none is available
!        * For some other terminals this is quite slow, that's why we don't do
!        * it.
!        */
!       len = read_from_input_buf(buf, (long)maxlen);
!       if (len > 0)
!           return len;
      }
  }
  
      static void
--- 404,524 ----
  {
      int               len;
      int               interrupted = FALSE;
+     int               did_start_blocking = FALSE;
      long      wait_time;
+     long      elapsed_time = 0;
  #if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
      struct timeval  start_tv;
  
      gettimeofday(&start_tv, NULL);
  #endif
  
!     /* repeat until we got a character or waited long enough */
      for (;;)
      {
!       /* Check if window changed size while we were busy, perhaps the ":set
!        * columns=99" command was used. */
!       while (do_resize)
!           handle_resize();
  
  #ifdef MESSAGE_QUEUE
!       parse_queued_messages();
  #endif
+       if (wtime < 0 && did_start_blocking)
+           /* blocking and already waited for p_ut */
+           wait_time = -1;
+       else
+       {
+           if (wtime >= 0)
+               wait_time = wtime;
+           else
+               /* going to block after p_ut */
+               wait_time = p_ut;
  #if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
!           elapsed_time = elapsed(&start_tv);
  #endif
!           wait_time -= elapsed_time;
!           if (wait_time < 0)
!           {
!               if (wtime >= 0)
!                   /* no character available within "wtime" */
!                   return 0;
! 
!               if (wtime < 0)
!               {
!                   /* no character available within 'updatetime' */
!                   did_start_blocking = TRUE;
  #ifdef FEAT_AUTOCMD
!                   if (trigger_cursorhold() && maxlen >= 3
!                                           && !typebuf_changed(tb_change_cnt))
!                   {
!                       buf[0] = K_SPECIAL;
!                       buf[1] = KS_EXTRA;
!                       buf[2] = (int)KE_CURSORHOLD;
!                       return 3;
!                   }
! #endif
!                   /*
!                    * If there is no character available within 'updatetime'
!                    * seconds flush all the swap files to disk.
!                    * Also done when interrupted by SIGWINCH.
!                    */
!                   before_blocking();
!                   continue;
!               }
!           }
        }
  
! #ifdef FEAT_JOB_CHANNEL
!       /* Checking if a job ended requires polling.  Do this every 100 msec. */
!       if (has_pending_job() && (wait_time < 0 || wait_time > 100L))
!           wait_time = 100L;
  #endif
+ 
        /*
         * We want to be interrupted by the winch signal
         * or by an event on the monitored file descriptors.
         */
!       if (WaitForChar(wait_time, &interrupted))
        {
!           /* If input was put directly in typeahead buffer bail out here. */
!           if (typebuf_changed(tb_change_cnt))
!               return 0;
! 
!           /*
!            * For some terminals we only get one character at a time.
!            * We want the get all available characters, so we could keep on
!            * trying until none is available
!            * For some other terminals this is quite slow, that's why we don't
!            * do it.
!            */
!           len = read_from_input_buf(buf, (long)maxlen);
!           if (len > 0)
!               return len;
!           continue;
        }
  
!       /* no character available */
! #if !(defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H))
!       /* estimate the elapsed time */
!       elapsed += wait_time;
! #endif
  
!       if (do_resize       /* interrupted by SIGWINCH signal */
! #ifdef FEAT_CLIENTSERVER
!               || server_waiting()
! #endif
! #ifdef MESSAGE_QUEUE
!               || interrupted
! #endif
!               || wait_time > 0
!               || !did_start_blocking)
!           continue;
! 
!       /* no character available or interrupted */
!       break;
      }
+     return 0;
  }
  
      static void
*** ../vim-8.0.0049/src/testdir/shared.vim      2016-08-22 21:30:05.000000000 
+0200
--- src/testdir/shared.vim      2016-10-27 19:51:53.040346452 +0200
***************
*** 136,141 ****
--- 136,169 ----
    return 1000
  endfunc
  
+ " Wait for up to a given milliseconds.
+ " With the +timers feature this waits for key-input by getchar(), Resume()
+ " feeds key-input and resumes process. Return time waited in milliseconds.
+ " Without +timers it uses simply :sleep.
+ func Standby(msec)
+   if has('timers')
+     let start = reltime()
+     let g:_standby_timer = timer_start(a:msec, function('s:feedkeys'))
+     call getchar()
+     return float2nr(reltimefloat(reltime(start)) * 1000)
+   else
+     execute 'sleep ' a:msec . 'm'
+     return a:msec
+   endif
+ endfunc
+ 
+ func Resume()
+   if exists('g:_standby_timer')
+     call timer_stop(g:_standby_timer)
+     call s:feedkeys(0)
+     unlet g:_standby_timer
+   endif
+ endfunc
+ 
+ func s:feedkeys(timer)
+   call feedkeys('x', 'nt')
+ endfunc
+ 
  " Run Vim, using the "vimcmd" file and "-u NORC".
  " "before" is a list of Vim commands to be executed before loading plugins.
  " "after" is a list of Vim commands to be executed after loading plugins.
*** ../vim-8.0.0049/src/testdir/test_channel.vim        2016-10-18 
16:27:20.544756017 +0200
--- src/testdir/test_channel.vim        2016-10-27 18:09:46.713670034 +0200
***************
*** 1362,1370 ****
    endif
  endfunc
  
- let g:exit_cb_time = {'start': 0, 'end': 0}
  function MyExitTimeCb(job, status)
!   let g:exit_cb_time.end = reltime(g:exit_cb_time.start)
  endfunction
  
  func Test_exit_callback_interval()
--- 1362,1372 ----
    endif
  endfunc
  
  function MyExitTimeCb(job, status)
!   if job_info(a:job).process == g:exit_cb_val.process
!     let g:exit_cb_val.end = reltime(g:exit_cb_val.start)
!   endif
!   call Resume()
  endfunction
  
  func Test_exit_callback_interval()
***************
*** 1372,1382 ****
      return
    endif
  
!   let g:exit_cb_time.start = reltime()
    let job = job_start([s:python, '-c', 'import time;time.sleep(0.5)'], 
{'exit_cb': 'MyExitTimeCb'})
!   call WaitFor('g:exit_cb_time.end != 0')
!   let elapsed = reltimefloat(g:exit_cb_time.end)
!   call assert_true(elapsed > 0.3)
    call assert_true(elapsed < 1.0)
  endfunc
  
--- 1374,1403 ----
      return
    endif
  
!   let g:exit_cb_val = {'start': reltime(), 'end': 0, 'process': 0}
    let job = job_start([s:python, '-c', 'import time;time.sleep(0.5)'], 
{'exit_cb': 'MyExitTimeCb'})
!   let g:exit_cb_val.process = job_info(job).process
!   call WaitFor('type(g:exit_cb_val.end) != v:t_number || g:exit_cb_val.end != 
0')
!   let elapsed = reltimefloat(g:exit_cb_val.end)
!   call assert_true(elapsed > 0.5)
!   call assert_true(elapsed < 1.0)
! 
!   " case: unreferenced job, using timer
!   if !has('timers')
!     return
!   endif
! 
!   let g:exit_cb_val = {'start': reltime(), 'end': 0, 'process': 0}
!   let g:job = job_start([s:python, '-c', 'import time;time.sleep(0.5)'], 
{'exit_cb': 'MyExitTimeCb'})
!   let g:exit_cb_val.process = job_info(g:job).process
!   unlet g:job
!   call Standby(1000)
!   if type(g:exit_cb_val.end) != v:t_number || g:exit_cb_val.end != 0
!     let elapsed = reltimefloat(g:exit_cb_val.end)
!   else
!     let elapsed = 1.0
!   endif
!   call assert_true(elapsed > 0.5)
    call assert_true(elapsed < 1.0)
  endfunc
  
*** ../vim-8.0.0049/src/version.c       2016-10-27 17:27:38.269074145 +0200
--- src/version.c       2016-10-27 19:54:19.827452177 +0200
***************
*** 766,767 ****
--- 766,769 ----
  {   /* Add new patch number below this line */
+ /**/
+     50,
  /**/

-- 
CART DRIVER: Bring out your dead!
   We follow the cart through a wretched, impoverished plague-ridden village.
   A few starved mongrels run about in the mud scavenging.  In the open
   doorway of one house perhaps we jug glimpse a pair of legs dangling from
   the ceiling.  In another doorway an OLD WOMAN is beating a cat against a
   wall rather like one does with a mat.  The cart passes round a dead donkey
   or cow in the mud.  And a MAN tied to a cart is being hammered to death by
   four NUNS with huge mallets.
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// 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