0
0
mirror of https://github.com/vim/vim.git synced 2025-09-26 04:04:07 -04:00

patch 8.0.0097

Problem:    When a channel callback consumes a lot of time Vim becomes
            unresponsive. (skywind)
Solution:   Bail out of checking channel readahead after 100 msec.
This commit is contained in:
Bram Moolenaar
2016-11-24 17:22:50 +01:00
parent 2cab0e1910
commit 833eb1d752
6 changed files with 88 additions and 48 deletions

View File

@@ -3815,6 +3815,11 @@ channel_parse_messages(void)
int ret = FALSE; int ret = FALSE;
int r; int r;
ch_part_T part = PART_SOCK; ch_part_T part = PART_SOCK;
#ifdef ELAPSED_FUNC
ELAPSED_TYPE start_tv;
ELAPSED_INIT(start_tv);
#endif
++safe_to_invoke_callback; ++safe_to_invoke_callback;
@@ -3859,7 +3864,14 @@ channel_parse_messages(void)
r = may_invoke_callback(channel, part); r = may_invoke_callback(channel, part);
if (r == OK) if (r == OK)
ret = TRUE; ret = TRUE;
if (channel_unref(channel) || r == OK) if (channel_unref(channel) || (r == OK
#ifdef ELAPSED_FUNC
/* Limit the time we loop here to 100 msec, otherwise
* Vim becomes unresponsive when the callback takes
* more than a bit of time. */
&& ELAPSED_FUNC(start_tv) < 100L
#endif
))
{ {
/* channel was freed or something was done, start over */ /* channel was freed or something was done, start over */
channel = first_channel; channel = first_channel;

View File

@@ -6263,3 +6263,34 @@ parse_queued_messages(void)
# endif # endif
} }
#endif #endif
#ifdef ELAPSED_TIMEVAL /* proto is defined in vim.h */
/*
* Return time in msec since "start_tv".
*/
long
elapsed(struct timeval *start_tv)
{
struct timeval now_tv;
gettimeofday(&now_tv, NULL);
return (now_tv.tv_sec - start_tv->tv_sec) * 1000L
+ (now_tv.tv_usec - start_tv->tv_usec) / 1000L;
}
#endif
#ifdef ELAPSED_TICKCOUNT
/*
* Return time in msec since "start_tick".
*/
long
elapsed(DWORD start_tick)
{
DWORD now = GetTickCount();
if (now < start_tick)
/* overflow */
return (long)now;
return (long)now - (long)start_tick;
}
#endif

View File

@@ -376,21 +376,6 @@ mch_write(char_u *s, int len)
RealWaitForChar(read_cmd_fd, p_wd, NULL, NULL); RealWaitForChar(read_cmd_fd, p_wd, NULL, NULL);
} }
#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
/*
* Return time in msec since "start_tv".
*/
static long
elapsed(struct timeval *start_tv)
{
struct timeval now_tv;
gettimeofday(&now_tv, NULL);
return (now_tv.tv_sec - start_tv->tv_sec) * 1000L
+ (now_tv.tv_usec - start_tv->tv_usec) / 1000L;
}
#endif
/* /*
* mch_inchar(): low level input function. * mch_inchar(): low level input function.
* Get a characters from the keyboard. * Get a characters from the keyboard.
@@ -411,10 +396,10 @@ mch_inchar(
int did_start_blocking = FALSE; int did_start_blocking = FALSE;
long wait_time; long wait_time;
long elapsed_time = 0; long elapsed_time = 0;
#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) #ifdef ELAPSED_FUNC
struct timeval start_tv; ELAPSED_TYPE start_tv;
gettimeofday(&start_tv, NULL); ELAPSED_INIT(start_tv);
#endif #endif
/* repeat until we got a character or waited long enough */ /* repeat until we got a character or waited long enough */
@@ -438,8 +423,8 @@ mch_inchar(
else else
/* going to block after p_ut */ /* going to block after p_ut */
wait_time = p_ut; wait_time = p_ut;
#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) #ifdef ELAPSED_FUNC
elapsed_time = elapsed(&start_tv); elapsed_time = ELAPSED_FUNC(start_tv);
#endif #endif
wait_time -= elapsed_time; wait_time -= elapsed_time;
if (wait_time < 0) if (wait_time < 0)
@@ -1554,18 +1539,16 @@ mch_input_isatty(void)
#ifdef FEAT_X11 #ifdef FEAT_X11
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) \ # if defined(ELAPSED_TIMEVAL) \
&& (defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE)) && (defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE))
static void xopen_message(struct timeval *start_tv);
/* /*
* Give a message about the elapsed time for opening the X window. * Give a message about the elapsed time for opening the X window.
*/ */
static void static void
xopen_message(struct timeval *start_tv) xopen_message(long elapsed_msec)
{ {
smsg((char_u *)_("Opening the X display took %ld msec"), elapsed(start_tv)); smsg((char_u *)_("Opening the X display took %ld msec"), elapsed_msec);
} }
# endif # endif
#endif #endif
@@ -1864,11 +1847,11 @@ get_x11_windis(void)
#endif #endif
if (x11_display != NULL) if (x11_display != NULL)
{ {
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) # ifdef ELAPSED_FUNC
if (p_verbose > 0) if (p_verbose > 0)
{ {
verbose_enter(); verbose_enter();
xopen_message(&start_tv); xopen_message(ELAPSED_FUNC(start_tv));
verbose_leave(); verbose_leave();
} }
# endif # endif
@@ -4630,8 +4613,8 @@ mch_call_shell(
ga_init2(&ga, 1, BUFLEN); ga_init2(&ga, 1, BUFLEN);
noread_cnt = 0; noread_cnt = 0;
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) # ifdef ELAPSED_FUNC
gettimeofday(&start_tv, NULL); ELAPSED_INIT(start_tv);
# endif # endif
for (;;) for (;;)
{ {
@@ -4666,8 +4649,8 @@ mch_call_shell(
/* Get extra characters when we don't have any. /* Get extra characters when we don't have any.
* Reset the counter and timer. */ * Reset the counter and timer. */
noread_cnt = 0; noread_cnt = 0;
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) # ifdef ELAPSED_FUNC
gettimeofday(&start_tv, NULL); ELAPSED_INIT(start_tv);
# endif # endif
len = ui_inchar(ta_buf, BUFLEN, 10L, 0); len = ui_inchar(ta_buf, BUFLEN, 10L, 0);
} }
@@ -4886,10 +4869,10 @@ mch_call_shell(
if (got_int) if (got_int)
break; break;
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) # ifdef ELAPSED_FUNC
if (wait_pid == 0) if (wait_pid == 0)
{ {
long msec = elapsed(&start_tv); long msec = ELAPSED_FUNC(start_tv);
/* Avoid that we keep looping here without /* Avoid that we keep looping here without
* checking for a CTRL-C for a long time. Don't * checking for a CTRL-C for a long time. Don't
@@ -5632,15 +5615,14 @@ RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *interrupted)
/* May retry getting characters after an event was handled. */ /* May retry getting characters after an event was handled. */
# define MAY_LOOP # define MAY_LOOP
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) # ifdef ELAPSED_FUNC
/* Remember at what time we started, so that we know how much longer we /* Remember at what time we started, so that we know how much longer we
* should wait after being interrupted. */ * should wait after being interrupted. */
# define USE_START_TV
long start_msec = msec; long start_msec = msec;
struct timeval start_tv; ELAPSED_TYPE start_tv;
if (msec > 0) if (msec > 0)
gettimeofday(&start_tv, NULL); ELAPSED_INIT(start_tv);
# endif # endif
/* Handle being called recursively. This may happen for the session /* Handle being called recursively. This may happen for the session
@@ -5947,9 +5929,9 @@ select_eintr:
/* We're going to loop around again, find out for how long */ /* We're going to loop around again, find out for how long */
if (msec > 0) if (msec > 0)
{ {
# ifdef USE_START_TV # ifdef ELAPSED_FUNC
/* Compute remaining wait time. */ /* Compute remaining wait time. */
msec = start_msec - elapsed(&start_tv); msec = start_msec - ELAPSED_FUNC(start_tv);
# else # else
/* Guess we got interrupted halfway. */ /* Guess we got interrupted halfway. */
msec = msec / 2; msec = msec / 2;
@@ -7046,11 +7028,11 @@ setup_term_clip(void)
#if defined(HAVE_SETJMP_H) #if defined(HAVE_SETJMP_H)
int (*oldIOhandler)(); int (*oldIOhandler)();
#endif #endif
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) # ifdef ELAPSED_FUNC
struct timeval start_tv; ELAPSED_TYPE start_tv;
if (p_verbose > 0) if (p_verbose > 0)
gettimeofday(&start_tv, NULL); ELAPSED_INIT(start_tv);
# endif # endif
/* Ignore X errors while opening the display */ /* Ignore X errors while opening the display */
@@ -7092,11 +7074,11 @@ setup_term_clip(void)
/* Catch terminating error of the X server connection. */ /* Catch terminating error of the X server connection. */
(void)XSetIOErrorHandler(x_IOerror_handler); (void)XSetIOErrorHandler(x_IOerror_handler);
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) # ifdef ELAPSED_FUNC
if (p_verbose > 0) if (p_verbose > 0)
{ {
verbose_enter(); verbose_enter();
xopen_message(&start_tv); xopen_message(ELAPSED_FUNC(start_tv));
verbose_leave(); verbose_leave();
} }
# endif # endif

View File

@@ -4287,9 +4287,6 @@ mch_system_piped(char *cmd, int options)
/* Get extra characters when we don't have any. Reset the /* Get extra characters when we don't have any. Reset the
* counter and timer. */ * counter and timer. */
noread_cnt = 0; noread_cnt = 0;
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
gettimeofday(&start_tv, NULL);
# endif
len = ui_inchar(ta_buf, BUFLEN, 10L, 0); len = ui_inchar(ta_buf, BUFLEN, 10L, 0);
} }
if (ta_len > 0 || len > 0) if (ta_len > 0 || len > 0)

View File

@@ -764,6 +764,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
97,
/**/ /**/
96, 96,
/**/ /**/

View File

@@ -2503,4 +2503,20 @@ typedef enum
# define OPEN_CHR_FILES # define OPEN_CHR_FILES
#endif #endif
#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
# define ELAPSED_TIMEVAL
# define ELAPSED_INIT(v) gettimeofday(&v, NULL)
# define ELAPSED_FUNC(v) elapsed(&v)
# define ELAPSED_TYPE struct timeval
long elapsed(struct timeval *start_tv);
#else
# if defined(WIN32)
# define ELAPSED_TICKCOUNT
# define ELAPSED_INIT(v) v = GetTickCount
# define ELAPSED_FUNC(v) elapsed(v)
# define ELAPSED_TYPE DWORD
long elapsed(DWORD start_tick);
# endif
#endif
#endif /* VIM__H */ #endif /* VIM__H */