[Toybox] Ok, I've given myself a headache trying to understand this one.

Rob Landley rob at landley.net
Fri May 29 08:22:08 PDT 2020


Running a mkroot build, it went:

Compile toybox....scripts/make.sh: line 34: echo: write error: Resource
temporarily unavailable
...scripts/make.sh: line 34: echo: write error: Resource temporarily unavailable
............scripts/make.sh: line 34: echo: write error: Resource temporarily
unavailable

Line 34 is:

  [ ! -z "$V" ] && echo "$@" || echo -n "$DOTPROG"

This is a bash script, so in THEORY this is the built-in bash echo. $DOTPROG
resolves to "." so in theory it's printing out a bunch of ... like it did a few
lines earlier without incident:

Compile
toybox.............................................................................................................................................................................................

I have no idea why the pipe or terminal it's outputting to is congested. There's
nothing in dmesg about it. But that's not the problem: I _assume_ bash's echo
won't output a message for that, and my echo should not output a message for
this either. (temporarily means it should retry? My echo hasn't set any signal
handlers and the default behavior is SA_RESTART?)

Yes, it's running with PATH=$PWD/root/airlock with just toybox binaries in it
including sh, but it's a #!/bin/bash script and which means echo is a builtin?
(Calling a function shouldn't change that?) My code doesn't have the string
"write error" in main.c lib/*.c or toys/*/*/c (except pending), and it's not in
musl either. (Although the airlock toybox is built against glibc so _IF_ my echo
is somehow getting called maybe it's picking it up from there, somehow? if
!FLAG(e) my echo is just calling xprintf() which calls xflush which does:

// if !flush just check for error on stdout without flushing
void xflush(int flush)
{
  if ((flush && fflush(0)) || ferror(stdout))
    if (!toys.exitval) perror_msg("write");
}

Which means if I _do_ somehow hit this error mine should say:

  echo: write: strerror_output

and that's saying "write error:" with the colon in the wrong place even for libc
having returned the string "error" as part of strerror_output. So I don't THINK
this is me?

But I am still DEEPLY CONFUSED. (And I also want to make sure my code doesn't
ever do this when it _is_ me... I thought the default signal handling was
SA_RESTART these days? I have to _disable_ that for some of the terminal control
handling stuff in my shell, I've got TODOs for it. And if it WAS running my
shell... it wouldn't get that far because the code's in pieces all over the
floor, I'm halfway through adding wildcard support. But if it DID I'd want to
make sure the signal handlers were in the right state for the builtin commands...)

Still confused,

Rob

P.S. Seriously, when I say "I break everything"... you may ask "how could you
possibly hit $STRANGE_CASE" and I'll go
http://lkml.iu.edu/hypermail/linux/kernel/0407.3/0027.html is where I hit a 1
instruction race that resulted in CVE https://usn.ubuntu.com/38-1/ . Seriously,
this is my normal workflow.


More information about the Toybox mailing list