BB: manually writes echo's buffer So setvbuf() may or may not have worked, since we don't get *any* error feedback from echo! When we set to linebuffering, fflush() does not return any errors. The kernel sets errno and returns -1. fflush clears errno at some point and returns 0, instead of EOF. I spent too much time wading through glibc's 10 levels of indirection and don't know why this happens. If we use block buffering instead of line, fflush works fine. This limits echo's to 4096 chars. Whatever. We're more likely to find another issue than to have an echo that long. Make clean and make busybox.
diff --git a/tools/apps/busybox/akaros-patches/1.17.3/0006-echo-linebuffered.patch b/tools/apps/busybox/akaros-patches/1.17.3/0006-echo-linebuffered.patch deleted file mode 100644 index 99c279a..0000000 --- a/tools/apps/busybox/akaros-patches/1.17.3/0006-echo-linebuffered.patch +++ /dev/null
@@ -1,14 +0,0 @@ -diff -ur busybox-1.17.3-akaros-orig/coreutils/echo.c busybox-1.17.3-akaros/coreutils/echo.c ---- busybox-1.17.3-akaros-orig/coreutils/echo.c 2015-03-02 11:35:58.782323515 -0500 -+++ busybox-1.17.3-akaros/coreutils/echo.c 2015-03-02 11:37:31.122641120 -0500 -@@ -96,6 +96,10 @@ - } - just_echo: - #endif -+ /* brho: need to buffer a full line at a time. not sure if glibc should -+ * have this set for stdout or not. */ -+ if (setvbuf(stdout, 0, _IOLBF, 0)) -+ perror("Failed to setvbuf"); - while (1) { - /* arg is already == *argv and isn't NULL */ - int c;
diff --git a/tools/apps/busybox/akaros-patches/1.17.3/0007-echo-buffering.patch b/tools/apps/busybox/akaros-patches/1.17.3/0007-echo-buffering.patch new file mode 100644 index 0000000..9212a2d --- /dev/null +++ b/tools/apps/busybox/akaros-patches/1.17.3/0007-echo-buffering.patch
@@ -0,0 +1,65 @@ +diff -ru busybox-1.17.3-orig/coreutils/echo.c busybox-1.17.3-akaros/coreutils/echo.c +--- busybox-1.17.3-orig/coreutils/echo.c 2015-03-06 12:06:11.732280338 -0500 ++++ busybox-1.17.3-akaros/coreutils/echo.c 2015-03-06 12:34:12.607118758 -0500 +@@ -33,6 +33,12 @@ + { + int ret; + const char *arg; ++ /* In lieu of using fputs/fflush, Akaros works better with raw writes. The ++ * main issue is that we want to have the entire echo sent as one write. ++ * using setvbuf for line buffered mode seems to work, but fflush won't ++ * propagate errors from the kernel. */ ++ char write_buf[4096]; ++ size_t buf_idx = 0; + #if !ENABLE_FEATURE_FANCY_ECHO + enum { + eflag = '\\', +@@ -100,12 +106,7 @@ + /* arg is already == *argv and isn't NULL */ + int c; + +- if (!eflag) { +- /* optimization for very common case */ +- ret = fputs(arg, stdout); +- if (ret == EOF) +- perror("echo failed"); +- } else while ((c = *arg++)) { ++ while ((c = *arg++)) { + if (c == eflag) { /* Check for escape seq. */ + if (*arg == 'c') { + /* '\c' means cancel newline and +@@ -130,25 +131,27 @@ + c = bb_process_escape_sequence(&arg); + } + } +- bb_putchar(c); ++ write_buf[buf_idx++] = c; + } + + arg = *++argv; + if (!arg) + break; +- bb_putchar(' '); ++ write_buf[buf_idx++] = ' '; + } + + newline_ret: + if (nflag) { +- bb_putchar('\n'); ++ write_buf[buf_idx++] = '\n'; + } + ret: +- errno = 0; +- ret = fflush_all(); +- if (errno) ++ ret = write(1, write_buf, buf_idx); ++ if (ret == -1) { + perror("echo failed"); +- return ret; ++ return EOF; ++ } else { ++ return 0; ++ } + } + + /*-