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.