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

function                                             old     new   delta
read_lines                                           685     733     +48

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2014-04-07 23:32:29 +02:00
parent 32afd3aa60
commit 69b114fb8a

View File

@ -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 */