busybox: 'ash: write error: EPIPE' when piping some large text variable into head command
To reproduce:
-
edit /etc/rc.psh in rootskel like that (for posixsrv run in background):

-
run system image
-
run /bin/psh /etc/rc.psh (for posixsrv run in background)
-
run /bin/sh
-
run text='yes abc | head -c 9999'
-
run echo "$text" | head -c 5
Code in echo.c which prints the error (full_write() sets errno to EPIPE):
errno = 0;
/*r =*/ full_write(STDOUT_FILENO, buffer, out - buffer);
free(buffer);
if (/*WRONG:r < 0*/ errno) {
bb_perror_msg(bb_msg_write_error);
return 1;
}
Busybox applets (echo in this case) assume correct SIGPIPE signal behaviour which terminates the process.
As a quick check I modified proc_write() in kernel so that SIGPIPE signal gets sent:
err = proc_send(oid.port, msg);
if (err >= 0) {
if ((err = msg->o.io.err) == -EPIPE)
threads_sigpost(proc_current()->process, proc_current(), 13 /*SIGPIPE*/);
}
As a result default SIGPIPE signal handler terminates the process and error messages no longer appear on the screen:

Please note that 'the quick check' probably isn't a correct way of sending SIGPIPE signal - I'll check how it should be done.
Verified on host (linux) that the echo $text process is being killed by SIGPIPE (incomplete write) if the write size exceeds the kernel pipe buffer (65535 bytes by default), code to reproduce:
strace -f busybox ash -c 'text=$(yes abc | head -c 655360); busybox echo $text | busybox head -c 5'

I don't know if the EPIPE errno is being set in case of partial write (to be checked).