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:
parent
32afd3aa60
commit
69b114fb8a
@ -404,6 +404,9 @@ static void fill_match_lines(unsigned pos);
|
|||||||
* last_line_pos - screen line position of next char to be read
|
* last_line_pos - screen line position of next char to be read
|
||||||
* (takes into account tabs and backspaces)
|
* (takes into account tabs and backspaces)
|
||||||
* eof_error - < 0 error, == 0 EOF, > 0 not EOF/error
|
* 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)
|
static void read_lines(void)
|
||||||
{
|
{
|
||||||
@ -414,9 +417,13 @@ static void read_lines(void)
|
|||||||
#if ENABLE_FEATURE_LESS_REGEXP
|
#if ENABLE_FEATURE_LESS_REGEXP
|
||||||
unsigned old_max_fline = max_fline;
|
unsigned old_max_fline = max_fline;
|
||||||
time_t last_time = 0;
|
time_t last_time = 0;
|
||||||
unsigned seconds_p1 = 3; /* seconds_to_loop + 1 */
|
int had_progress = 2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* (careful: max_fline can be -1) */
|
||||||
|
if (max_fline + 1 > MAXLINES)
|
||||||
|
return;
|
||||||
|
|
||||||
if (option_mask32 & FLAG_N)
|
if (option_mask32 & FLAG_N)
|
||||||
w -= 8;
|
w -= 8;
|
||||||
|
|
||||||
@ -441,6 +448,7 @@ static void read_lines(void)
|
|||||||
char c;
|
char c;
|
||||||
/* if no unprocessed chars left, eat more */
|
/* if no unprocessed chars left, eat more */
|
||||||
if (readpos >= readeof) {
|
if (readpos >= readeof) {
|
||||||
|
errno = 0;
|
||||||
ndelay_on(0);
|
ndelay_on(0);
|
||||||
eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf));
|
eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf));
|
||||||
ndelay_off(0);
|
ndelay_off(0);
|
||||||
@ -448,6 +456,7 @@ static void read_lines(void)
|
|||||||
readeof = eof_error;
|
readeof = eof_error;
|
||||||
if (eof_error <= 0)
|
if (eof_error <= 0)
|
||||||
goto reached_eof;
|
goto reached_eof;
|
||||||
|
had_progress = 1;
|
||||||
}
|
}
|
||||||
c = readbuf[readpos];
|
c = readbuf[readpos];
|
||||||
/* backspace? [needed for manpages] */
|
/* backspace? [needed for manpages] */
|
||||||
@ -519,31 +528,23 @@ static void read_lines(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (eof_error <= 0) {
|
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
|
#if !ENABLE_FEATURE_LESS_REGEXP
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
if (wanted_match < num_matches) {
|
if (wanted_match < num_matches) {
|
||||||
break;
|
break;
|
||||||
} else { /* goto_match called us */
|
} /* else: goto_match() called us */
|
||||||
|
if (errno == EAGAIN) {
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
if (t != last_time) {
|
if (t != last_time) {
|
||||||
last_time = t;
|
last_time = t;
|
||||||
if (--seconds_p1 == 0)
|
if (--had_progress < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sched_yield();
|
sched_yield();
|
||||||
goto again0; /* go loop again (max 2 seconds) */
|
goto again0;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
max_fline++;
|
max_fline++;
|
||||||
@ -551,6 +552,15 @@ static void read_lines(void)
|
|||||||
p = current_line;
|
p = current_line;
|
||||||
last_line_pos = 0;
|
last_line_pos = 0;
|
||||||
} /* end of "read lines until we reach cur_fline" loop */
|
} /* 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);
|
fill_match_lines(old_max_fline);
|
||||||
#if ENABLE_FEATURE_LESS_REGEXP
|
#if ENABLE_FEATURE_LESS_REGEXP
|
||||||
/* prevent us from being stuck in search for a match */
|
/* prevent us from being stuck in search for a match */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user