changeset 10406:42911b233245 v8.0.0097

commit https://github.com/vim/vim/commit/833eb1d752426689051bf2001083359899536939 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Nov 24 17:22:50 2016 +0100 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.
author Christian Brabandt <cb@256bit.org>
date Thu, 24 Nov 2016 17:30:04 +0100
parents 4d35d83f4537
children 909ea30c733e
files src/channel.c src/misc2.c src/os_unix.c src/os_win32.c src/version.c src/vim.h
diffstat 6 files changed, 90 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- 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;
--- 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
--- 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;
-
-    gettimeofday(&start_tv, NULL);
+#ifdef ELAPSED_FUNC
+    ELAPSED_TYPE start_tv;
+
+    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)
-{
-    smsg((char_u *)_("Opening the X display took %ld msec"), elapsed(start_tv));
+xopen_message(long elapsed_msec)
+{
+    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 *
     /* 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
--- 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)
--- 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,
--- 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 */