diff src/search.c @ 11521:578df034735d v8.0.0643

patch 8.0.0643: when a pattern search is slow Vim becomes unusable commit https://github.com/vim/vim/commit/fbd0b0af6800f6ff89857863d6a07ea03f09ff6c Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jun 17 18:44:21 2017 +0200 patch 8.0.0643: when a pattern search is slow Vim becomes unusable Problem: When 'hlsearch' is set and matching with the last search pattern is very slow, Vim becomes unusable. Cannot quit search by pressing CTRL-C. Solution: When the search times out set a flag and don't try again. Check for timeout and CTRL-C in NFA loop that adds states.
author Christian Brabandt <cb@256bit.org>
date Sat, 17 Jun 2017 18:45:04 +0200
parents 9473793c7bb5
children 5e36b2f825cb
line wrap: on
line diff
--- a/src/search.c
+++ b/src/search.c
@@ -593,7 +593,8 @@ searchit(
     int		options,
     int		pat_use,	/* which pattern to use when "pat" is empty */
     linenr_T	stop_lnum,	/* stop after this line number when != 0 */
-    proftime_T	*tm UNUSED)	/* timeout limit or NULL */
+    proftime_T	*tm UNUSED,	/* timeout limit or NULL */
+    int		*timed_out UNUSED)  /* set when timed out or NULL */
 {
     int		found;
     linenr_T	lnum;		/* no init to shut up Apollo cc */
@@ -715,13 +716,17 @@ searchit(
 		nmatched = vim_regexec_multi(&regmatch, win, buf,
 					     lnum, col,
 #ifdef FEAT_RELTIME
-					     tm
+					     tm, timed_out
 #else
-					     NULL
+					     NULL, NULL
 #endif
 						      );
 		/* Abort searching on an error (e.g., out of stack). */
-		if (called_emsg)
+		if (called_emsg
+#ifdef FEAT_RELTIME
+			|| (timed_out != NULL && *timed_out)
+#endif
+			)
 		    break;
 		if (nmatched > 0)
 		{
@@ -810,9 +815,9 @@ searchit(
 					      win, buf, lnum + matchpos.lnum,
 					      matchcol,
 #ifdef FEAT_RELTIME
-					      tm
+					      tm, timed_out
 #else
-					      NULL
+					      NULL, NULL
 #endif
 					      )) == 0)
 			    {
@@ -922,9 +927,9 @@ searchit(
 					      win, buf, lnum + matchpos.lnum,
 					      matchcol,
 #ifdef FEAT_RELTIME
-					      tm
+					      tm, timed_out
 #else
-					      NULL
+					      NULL, NULL
 #endif
 					    )) == 0)
 				break;
@@ -1019,10 +1024,13 @@ searchit(
 	     * twice.
 	     */
 	    if (!p_ws || stop_lnum != 0 || got_int || called_emsg
+#ifdef FEAT_RELTIME
+				|| (timed_out != NULL && *timed_out)
+#endif
 #ifdef FEAT_SEARCH_EXTRA
-					       || break_loop
+				|| break_loop
 #endif
-					       || found || loop)
+				|| found || loop)
 		break;
 
 	    /*
@@ -1041,6 +1049,9 @@ searchit(
 					  ? top_bot_msg : bot_top_msg), TRUE);
 	}
 	if (got_int || called_emsg
+#ifdef FEAT_RELTIME
+		|| (timed_out != NULL && *timed_out)
+#endif
 #ifdef FEAT_SEARCH_EXTRA
 		|| break_loop
 #endif
@@ -1147,7 +1158,8 @@ do_search(
     char_u	    *pat,
     long	    count,
     int		    options,
-    proftime_T	    *tm)	/* timeout limit or NULL */
+    proftime_T	    *tm,	/* timeout limit or NULL */
+    int		    *timed_out) /* flag set on timeout or NULL */
 {
     pos_T	    pos;	/* position of the last match */
     char_u	    *searchstr;
@@ -1433,7 +1445,7 @@ do_search(
 		       (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS
 			+ SEARCH_MSG + SEARCH_START
 			+ ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF))),
-		RE_LAST, (linenr_T)0, tm);
+		RE_LAST, (linenr_T)0, tm, timed_out);
 
 	if (dircp != NULL)
 	    *dircp = dirc;	/* restore second '/' or '?' for normal_cmd() */
@@ -4672,7 +4684,7 @@ current_search(
 
 	result = searchit(curwin, curbuf, &pos, (dir ? FORWARD : BACKWARD),
 		spats[last_idx].pat, (long) (i ? count : 1),
-		SEARCH_KEEP | flags, RE_SEARCH, 0, NULL);
+		SEARCH_KEEP | flags, RE_SEARCH, 0, NULL, NULL);
 
 	/* First search may fail, but then start searching from the
 	 * beginning of the file (cursor might be on the search match)
@@ -4719,7 +4731,8 @@ current_search(
      * already on the next match */
     if (!one_char)
 	result = searchit(curwin, curbuf, &pos, (forward ? FORWARD : BACKWARD),
-	    spats[last_idx].pat, 0L, flags | SEARCH_KEEP, RE_SEARCH, 0, NULL);
+		    spats[last_idx].pat, 0L, flags | SEARCH_KEEP, RE_SEARCH, 0,
+								   NULL, NULL);
 
     if (!VIsual_active)
 	VIsual = start_pos;
@@ -4800,7 +4813,7 @@ is_one_char(char_u *pattern, int move, p
     }
 
     if (searchit(curwin, curbuf, &pos, FORWARD, pattern, 1,
-			      SEARCH_KEEP + flag, RE_SEARCH, 0, NULL) != FAIL)
+			 SEARCH_KEEP + flag, RE_SEARCH, 0, NULL, NULL) != FAIL)
     {
 	/* Zero-width pattern should match somewhere, then we can check if
 	 * start and end are in the same position. */
@@ -4809,7 +4822,7 @@ is_one_char(char_u *pattern, int move, p
 	{
 	    regmatch.startpos[0].col++;
 	    nmatched = vim_regexec_multi(&regmatch, curwin, curbuf,
-					    pos.lnum, regmatch.startpos[0].col, NULL);
+			       pos.lnum, regmatch.startpos[0].col, NULL, NULL);
 	    if (!nmatched)
 		break;
 	} while (regmatch.startpos[0].col < pos.col);