Here is a patch which invokes kill_myself_with_sig(SIGPIPE) if fwrite fails with errno=EPIPE.
Quitting with a signal rather than a diagnostic output emulates GNU tee which is in line with the apparent reason for busybox tee in ignoring SIGPIPE in the first place. I have tested it with and without CONFIG_FEATURE_TEE_USE_BLOCK_IO=y As expected, dd succeeds for bs=1024 with CONFIG_FEATURE_TEE_USE_BLOCK_IO=y but fails for without. dd fails in both cases for bs=1024000 tee fails in both cases ( sleep 2 ; dd if=/dev/zero bs=1024000 count=5 ; echo dd $? > /dev/tty ; ) | { build_output/sysroots-components/x86_64/busybox-native/bin/busybox.nosuid tee /dev/null ; echo tee $? >/dev/tty ; } | sleep 1 ( sleep 2 ; dd if=/dev/zero bs=1024 count=5 ; echo dd $? > /dev/tty ; ) | { build_output/sysroots-components/x86_64/busybox-native/bin/busybox.nosuid tee /dev/null ; echo tee $? >/dev/tty ; } | sleep 1 A colleague has suggested that *any* write failure to *stdout* by tee ought to cause tee to quit, but I leave this to your consideration; something like this *might* cover both cases but I haven't tested it: if (fwrite(buf, 1, c, *fp) != c) { if (errno == EPIPE) kill_myself_with_sig(SIGPIPE); retval = EXIT_FAILURE; break; } Sam On Thu, 12 Sep 2019 at 20:03, Sam Liddicott <s...@liddicott.com> wrote: > In https://git.busybox.net/busybox/tree/coreutils/tee.c we read: > > /* gnu tee ignores SIGPIPE in case one of the output files is a pipe > * that doesn't consume all its input. Good idea... */ > signal(SIGPIPE, SIG_IGN); > > > Sadly, this breaks POSIX SIGPIPE behaviour with respect to quitting when > stdout (as a pipe) is closed. > > Despite the comment, GNU tee does not behave as the comment suggests. > > Comparing 1.27.2-2ubuntu3.2 with tee (GNU coreutils) 8.28 > > I test with one output file and stdout that stops early causing SIGPIPE > > 1. GNU tee > > ( dd if=/dev/zero bs=1024 count=8192 ; echo done $? >&2 ) | ( tee > /dev/null ; echo tee $? >&2) | dd bs=10 count=10 >/dev/null > > 10+0 records in > 10+0 records out > 100 bytes copied, 0.000387276 s, 258 kB/s > tee 141 > done 141 > > the first two pipeline stages have exit code 141 due to sigpipe as we > would expect > > 2. busybox tee > > ( dd if=/dev/zero bs=1024 count=8192 ; echo done $? >&2 ) | ( busybox tee > /dev/null ; echo tee $? >&2) | dd bs=10 count=10 >/dev/null > 10+0 records in > 10+0 records out > 100 bytes copied, 0.000291134 s, 343 kB/s > 8192+0 records in > 8192+0 records out > 8388608 bytes (8.4 MB, 8.0 MiB) copied, 0.0447136 s, 188 MB/s > done 0 > tee 0 > > both prior pipeline elements have exit code zero and the first stage > processed all of the data > > The POSIX spec for tee reads: > https://pubs.opengroup.org/onlinepubs/9699919799/utilities/tee.html > CONSEQUENCES OF ERRORS > > If a write to any successfully opened *file* operand fails, writes to > other successfully opened *file* operands and standard output shall > continue, but the exit status shall be non-zero. Otherwise, the default > actions specified in *Utility Description Defaults* > <https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html#tag_17_04> > apply. > > But this case deals with a failure to write to stdout, not a failure to > write to a *file* operand. > > Certainly, with this behaviour, busybox tee does not comply with GNU tee > as it appears to intend, so I suggest that the line signal(SIGPIPE, > SIG_IGN) be removed. > > To meet the probable intent, the signal should probably be ignored while > writing to file operands (in case they turn out to be pipes) and enabled > each time when writing to stdout. > > Sam >
0001-Add-SIGPIPE-handler-to-tee.patch
Description: Binary data
_______________________________________________ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox