phoenix-rtos-project icon indicating copy to clipboard operation
phoenix-rtos-project copied to clipboard

busybox: 'ash: write error: EPIPE' when piping some large text variable into head command

Open damianloew opened this issue 4 years ago • 2 comments

Screenshot from 2021-08-12 13-00-55 To reproduce:

  1. edit /etc/rc.psh in rootskel like that (for posixsrv run in background): image

  2. run system image

  3. run /bin/psh /etc/rc.psh (for posixsrv run in background)

  4. run /bin/sh

  5. run text='yes abc | head -c 9999'

  6. run echo "$text" | head -c 5

damianloew avatar Aug 12 '21 11:08 damianloew

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: sigpipe

Please note that 'the quick check' probably isn't a correct way of sending SIGPIPE signal - I'll check how it should be done.

Maxez avatar Aug 17 '21 14:08 Maxez

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'

image

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

nalajcie avatar Aug 17 '21 15:08 nalajcie