less: move "retry-on-EAGAIN" logic closer to read ops
authorDenys Vlasenko <vda.linux@googlemail.com>
Mon, 22 Sep 2014 19:14:02 +0000 (21:14 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Mon, 22 Sep 2014 19:14:02 +0000 (21:14 +0200)
This makes "G" (goto end of input) command work as well as
/search_for_nonexistent_string: both will read to EOF now
even from somewhat slow input (such as kernel's "git log").

function                                             old     new   delta
ndelay_on                                             35      43      +8
ndelay_off                                            35      43      +8
read_lines                                           695     691      -4
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/1 up/down: 16/-4)              Total: 12 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
include/libbb.h
libbb/xfuncs.c
miscutils/less.c

index ff223dd0f520ff6ade20d1b880a8f026fad14b5a..d57f00e0e2f5f149ee87b6dd79b2b2ec80cdfc07 100644 (file)
@@ -390,8 +390,8 @@ const char *bb_basename(const char *name) FAST_FUNC;
 char *last_char_is(const char *s, int c) FAST_FUNC;
 const char* endofname(const char *name) FAST_FUNC;
 
-void ndelay_on(int fd) FAST_FUNC;
-void ndelay_off(int fd) FAST_FUNC;
+int ndelay_on(int fd) FAST_FUNC;
+int ndelay_off(int fd) FAST_FUNC;
 void close_on_exec_on(int fd) FAST_FUNC;
 void xdup2(int, int) FAST_FUNC;
 void xmove_fd(int, int) FAST_FUNC;
index 23f27516f633c2178f2b00b24e13aec5c9c2d357..f25ce944649d6516ec9d0faca69d4ec40b053104 100644 (file)
 #include "libbb.h"
 
 /* Turn on nonblocking I/O on a fd */
-void FAST_FUNC ndelay_on(int fd)
+int FAST_FUNC ndelay_on(int fd)
 {
        int flags = fcntl(fd, F_GETFL);
        if (flags & O_NONBLOCK)
-               return;
+               return flags;
        fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+       return flags;
 }
 
-void FAST_FUNC ndelay_off(int fd)
+int FAST_FUNC ndelay_off(int fd)
 {
        int flags = fcntl(fd, F_GETFL);
        if (!(flags & O_NONBLOCK))
-               return;
+               return flags;
        fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+       return flags;
 }
 
 void FAST_FUNC close_on_exec_on(int fd)
index 719af5a0dfe0d0e903381475d8c5225d3eac02a9..3016c5b47c69d4817cc30ba3bad81d34c6b7b722 100644 (file)
@@ -414,10 +414,10 @@ static void read_lines(void)
        char *current_line, *p;
        int w = width;
        char last_terminated = terminated;
+       time_t last_time = 0;
+       int retry_EAGAIN = 2;
 #if ENABLE_FEATURE_LESS_REGEXP
        unsigned old_max_fline = max_fline;
-       time_t last_time = 0;
-       int had_progress = 2;
 #endif
 
        /* (careful: max_fline can be -1) */
@@ -427,8 +427,6 @@ static void read_lines(void)
        if (option_mask32 & FLAG_N)
                w -= 8;
 
- IF_FEATURE_LESS_REGEXP(again0:)
-
        p = current_line = ((char*)xmalloc(w + 4)) + 4;
        max_fline += last_terminated;
        if (!last_terminated) {
@@ -448,15 +446,29 @@ 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);
+                               int flags = ndelay_on(0);
+
+                               while (1) {
+                                       time_t t;
+
+                                       errno = 0;
+                                       eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf));
+                                       if (errno != EAGAIN)
+                                               break;
+                                       t = time(NULL);
+                                       if (t != last_time) {
+                                               last_time = t;
+                                               if (--retry_EAGAIN < 0)
+                                                       break;
+                                       }
+                                       sched_yield();
+                               }
+                               fcntl(0, F_SETFL, flags); /* ndelay_off(0) */
                                readpos = 0;
                                readeof = eof_error;
                                if (eof_error <= 0)
                                        goto reached_eof;
-                               IF_FEATURE_LESS_REGEXP(had_progress = 1;)
+                               retry_EAGAIN = 1;
                        }
                        c = readbuf[readpos];
                        /* backspace? [needed for manpages] */
@@ -534,24 +546,7 @@ static void read_lines(void)
 #endif
                }
                if (eof_error <= 0) {
-#if !ENABLE_FEATURE_LESS_REGEXP
                        break;
-#else
-                       if (wanted_match < num_matches) {
-                               break;
-                       } /* else: goto_match() called us */
-                       if (errno == EAGAIN) {
-                               time_t t = time(NULL);
-                               if (t != last_time) {
-                                       last_time = t;
-                                       if (--had_progress < 0)
-                                               break;
-                               }
-                               sched_yield();
-                               goto again0;
-                       }
-                       break;
-#endif
                }
                max_fline++;
                current_line = ((char*)xmalloc(w + 4)) + 4;