summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-11-24 17:22:50 +0100
committerBram Moolenaar <Bram@vim.org>2016-11-24 17:22:50 +0100
commit833eb1d752426689051bf2001083359899536939 (patch)
treef91eeead037b689d8d02bd1e47704332a63d7de0
parent2cab0e191055a8145ccd46cd52869fbb9798b971 (diff)
downloadvim-git-833eb1d752426689051bf2001083359899536939.tar.gz
patch 8.0.0097v8.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.
-rw-r--r--src/channel.c14
-rw-r--r--src/misc2.c31
-rw-r--r--src/os_unix.c70
-rw-r--r--src/os_win32.c3
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h16
6 files changed, 88 insertions, 48 deletions
diff --git a/src/channel.c b/src/channel.c
index 778a30e17..19520e200 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -3815,6 +3815,11 @@ channel_parse_messages(void)
int ret = FALSE;
int r;
ch_part_T part = PART_SOCK;
+#ifdef ELAPSED_FUNC
+ ELAPSED_TYPE start_tv;
+
+ ELAPSED_INIT(start_tv);
+#endif
++safe_to_invoke_callback;
@@ -3859,7 +3864,14 @@ channel_parse_messages(void)
r = may_invoke_callback(channel, part);
if (r == OK)
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 = first_channel;
diff --git a/src/misc2.c b/src/misc2.c
index 27d26bece..9fa11e3d2 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -6263,3 +6263,34 @@ parse_queued_messages(void)
# 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
diff --git a/src/os_unix.c b/src/os_unix.c
index a63eb6e89..12fb33b7a 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -376,21 +376,6 @@ mch_write(char_u *s, int len)
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.
* Get a characters from the keyboard.
@@ -411,10 +396,10 @@ mch_inchar(
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;
+#ifdef ELAPSED_FUNC
+ ELAPSED_TYPE start_tv;
- gettimeofday(&start_tv, NULL);
+ ELAPSED_INIT(start_tv);
#endif
/* repeat until we got a character or waited long enough */
@@ -438,8 +423,8 @@ mch_inchar(
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);
+#ifdef ELAPSED_FUNC
+ elapsed_time = ELAPSED_FUNC(start_tv);
#endif
wait_time -= elapsed_time;
if (wait_time < 0)
@@ -1554,18 +1539,16 @@ mch_input_isatty(void)
#ifdef FEAT_X11
-# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) \
+# if defined(ELAPSED_TIMEVAL) \
&& (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.
*/
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
@@ -1864,11 +1847,11 @@ get_x11_windis(void)
#endif
if (x11_display != NULL)
{
-# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
+# ifdef ELAPSED_FUNC
if (p_verbose > 0)
{
verbose_enter();
- xopen_message(&start_tv);
+ xopen_message(ELAPSED_FUNC(start_tv));
verbose_leave();
}
# endif
@@ -4630,8 +4613,8 @@ mch_call_shell(
ga_init2(&ga, 1, BUFLEN);
noread_cnt = 0;
-# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
- gettimeofday(&start_tv, NULL);
+# ifdef ELAPSED_FUNC
+ ELAPSED_INIT(start_tv);
# endif
for (;;)
{
@@ -4666,8 +4649,8 @@ mch_call_shell(
/* Get extra characters when we don't have any.
* Reset the counter and timer. */
noread_cnt = 0;
-# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
- gettimeofday(&start_tv, NULL);
+# ifdef ELAPSED_FUNC
+ ELAPSED_INIT(start_tv);
# endif
len = ui_inchar(ta_buf, BUFLEN, 10L, 0);
}
@@ -4886,10 +4869,10 @@ mch_call_shell(
if (got_int)
break;
-# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
+# ifdef ELAPSED_FUNC
if (wait_pid == 0)
{
- long msec = elapsed(&start_tv);
+ long msec = ELAPSED_FUNC(start_tv);
/* Avoid that we keep looping here without
* 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. */
# 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
* should wait after being interrupted. */
-# define USE_START_TV
long start_msec = msec;
- struct timeval start_tv;
+ ELAPSED_TYPE start_tv;
if (msec > 0)
- gettimeofday(&start_tv, NULL);
+ ELAPSED_INIT(start_tv);
# endif
/* 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 */
if (msec > 0)
{
-# ifdef USE_START_TV
+# ifdef ELAPSED_FUNC
/* Compute remaining wait time. */
- msec = start_msec - elapsed(&start_tv);
+ msec = start_msec - ELAPSED_FUNC(start_tv);
# else
/* Guess we got interrupted halfway. */
msec = msec / 2;
@@ -7046,11 +7028,11 @@ setup_term_clip(void)
#if defined(HAVE_SETJMP_H)
int (*oldIOhandler)();
#endif
-# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
- struct timeval start_tv;
+# ifdef ELAPSED_FUNC
+ ELAPSED_TYPE start_tv;
if (p_verbose > 0)
- gettimeofday(&start_tv, NULL);
+ ELAPSED_INIT(start_tv);
# endif
/* Ignore X errors while opening the display */
@@ -7092,11 +7074,11 @@ setup_term_clip(void)
/* Catch terminating error of the X server connection. */
(void)XSetIOErrorHandler(x_IOerror_handler);
-# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
+# ifdef ELAPSED_FUNC
if (p_verbose > 0)
{
verbose_enter();
- xopen_message(&start_tv);
+ xopen_message(ELAPSED_FUNC(start_tv));
verbose_leave();
}
# endif
diff --git a/src/os_win32.c b/src/os_win32.c
index 34b2ca838..23044381d 100644
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -4287,9 +4287,6 @@ mch_system_piped(char *cmd, int options)
/* Get extra characters when we don't have any. Reset the
* counter and timer. */
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);
}
if (ta_len > 0 || len > 0)
diff --git a/src/version.c b/src/version.c
index e259000c0..076ed520c 100644
--- a/src/version.c
+++ b/src/version.c
@@ -765,6 +765,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 97,
+/**/
96,
/**/
95,
diff --git a/src/vim.h b/src/vim.h
index eec3e4f73..c91e52bb2 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -2503,4 +2503,20 @@ typedef enum
# define OPEN_CHR_FILES
#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 */