[git commit] less: fix bugs discovered with "git log -p | less -m" on kernel tree

Denys Vlasenko vda.linux at googlemail.com
Sun Apr 13 14:02:59 UTC 2014


commit: http://git.busybox.net/busybox/commit/?id=69b114fb8a2566e14ce125f7736add9dacf6e18d
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
read_lines                                           685     733     +48

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 miscutils/less.c |   38 ++++++++++++++++++++++++--------------
 1 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/miscutils/less.c b/miscutils/less.c
index 574f222..36d0a0b 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -404,6 +404,9 @@ static void fill_match_lines(unsigned pos);
  * last_line_pos - screen line position of next char to be read
  *      (takes into account tabs and backspaces)
  * eof_error - < 0 error, == 0 EOF, > 0 not EOF/error
+ *
+ * "git log -p | less -m" on the kernel git tree is a good test for EAGAINs,
+ * "/search on very long input" and "reaching max line count" corner cases.
  */
 static void read_lines(void)
 {
@@ -414,9 +417,13 @@ static void read_lines(void)
 #if ENABLE_FEATURE_LESS_REGEXP
 	unsigned old_max_fline = max_fline;
 	time_t last_time = 0;
-	unsigned seconds_p1 = 3; /* seconds_to_loop + 1 */
+	int had_progress = 2;
 #endif
 
+	/* (careful: max_fline can be -1) */
+	if (max_fline + 1 > MAXLINES)
+		return;
+
 	if (option_mask32 & FLAG_N)
 		w -= 8;
 
@@ -441,6 +448,7 @@ static void read_lines(void)
 			char c;
 			/* if no unprocessed chars left, eat more */
 			if (readpos >= readeof) {
+				errno = 0;
 				ndelay_on(0);
 				eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf));
 				ndelay_off(0);
@@ -448,6 +456,7 @@ static void read_lines(void)
 				readeof = eof_error;
 				if (eof_error <= 0)
 					goto reached_eof;
+				had_progress = 1;
 			}
 			c = readbuf[readpos];
 			/* backspace? [needed for manpages] */
@@ -519,31 +528,23 @@ static void read_lines(void)
 #endif
 		}
 		if (eof_error <= 0) {
-			if (eof_error < 0) {
-				if (errno == EAGAIN) {
-					/* not yet eof or error, reset flag (or else
-					 * we will hog CPU - select() will return
-					 * immediately */
-					eof_error = 1;
-				} else {
-					print_statusline(bb_msg_read_error);
-				}
-			}
 #if !ENABLE_FEATURE_LESS_REGEXP
 			break;
 #else
 			if (wanted_match < num_matches) {
 				break;
-			} else { /* goto_match called us */
+			} /* else: goto_match() called us */
+			if (errno == EAGAIN) {
 				time_t t = time(NULL);
 				if (t != last_time) {
 					last_time = t;
-					if (--seconds_p1 == 0)
+					if (--had_progress < 0)
 						break;
 				}
 				sched_yield();
-				goto again0; /* go loop again (max 2 seconds) */
+				goto again0;
 			}
+			break;
 #endif
 		}
 		max_fline++;
@@ -551,6 +552,15 @@ static void read_lines(void)
 		p = current_line;
 		last_line_pos = 0;
 	} /* end of "read lines until we reach cur_fline" loop */
+
+	if (eof_error < 0) {
+		if (errno == EAGAIN) {
+			eof_error = 1;
+		} else {
+			print_statusline(bb_msg_read_error);
+		}
+	}
+
 	fill_match_lines(old_max_fline);
 #if ENABLE_FEATURE_LESS_REGEXP
 	/* prevent us from being stuck in search for a match */


More information about the busybox-cvs mailing list