diff options
author | Pádraig Brady <P@draigBrady.com> | 2015-02-16 12:55:40 +0000 |
---|---|---|
committer | Pádraig Brady <P@draigBrady.com> | 2015-02-24 18:12:22 +0000 |
commit | fdd6ebf0ae786681e99afdaf1ef44bb750e66b2d (patch) | |
tree | 522b47c895184ea102345caa3bbea280dd223255 /tests/misc | |
parent | 19d34d244b46227e83ec43969f99c5e3b23ea01d (diff) | |
download | coreutils-fdd6ebf0ae786681e99afdaf1ef44bb750e66b2d.tar.xz |
tee: add --write-error to control handling of closed pipes
tee is very often used with pipes and this gives better control
when writing to them. There are 3 classes of file descriptors
that tee can write to: files(1), pipes(2), and early close pipes(3).
Handling write errors to 1 & 2 is supported at present with the caveat
that failure writing to any pipe will terminate tee immediately.
Handling write errors to type 3 is not currently supported.
To improve the supported combinations we add these options:
--write-error=warn
Warn if error writing any output including pipes.
Allows continued writing to still open files/pipes.
Exit status is failure if any output had error.
--write-error=warn-nopipe, -p
Warn if error writing any output except pipes.
Allows continued writing to still open files/pipes.
Exit status is failure if any non pipe output had error.
--write-error=exit
Exit if error writing any output including pipes.
--write-error=exit-nopipe
Exit if error writing any output except pipes.
Use the "nopipe" variants when files are of types 1 and 3, otherwise
use the standard variants with types 1 and 2. A caveat with the above
scheme is that a combination of pipe types (2 & 3) is not supported
robustly. I.e. if you use the "nopipe" variants when using both type
2 and 3 pipes, then any "real" errors on type 2 pipes will not be
diagnosed.
Note also a general issue with type 3 pipes that are not on tee's
stdout, is that shell constructs don't allow to distinguish early
close from real failures. For example `tee >(head -n1) | grep -m1 ..`
can't distinguish between an error or an early close in "head" pipe,
while the fail on the grep part of the pipe is distinguished
independently from the resulting pipe errors. This is a general
issue with the >() construct, rather than with tee itself.
* NEWS: Mention the new feature.
* doc/coreutils.texi (tee invocation): Describe the new option.
* src/tee.c (usage): Likewise.
(main): With --write-error ignore SIGPIPE, and handle
the various exit, diagnostics combinations.
* tests/misc/tee.sh: Tess all the new options.
Fixes http://bugs.gnu.org/11540
Diffstat (limited to 'tests/misc')
-rwxr-xr-x | tests/misc/tee.sh | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/tests/misc/tee.sh b/tests/misc/tee.sh index ecca6562b..84665cd00 100755 --- a/tests/misc/tee.sh +++ b/tests/misc/tee.sh @@ -63,4 +63,41 @@ if test -w /dev/full && test -c /dev/full; then test $(wc -l < err) = 1 || { cat err; fail=1; } fi + +# Ensure tee honors --write-error modes +mkfifo_or_skip_ fifo +read_fifo() { timeout 10 dd count=1 if=fifo of=/dev/null status=none & } + +# Determine platform sigpipe exit status +read_fifo +yes >fifo +pipe_status=$? + +# Default operation is to exit silently on SIGPIPE +read_fifo +yes | returns_ $pipe_status timeout 10 tee 2>err >fifo || fail=1 +test $(wc -l < err) = 0 || { cat err; fail=1; } + +# With -p, SIGPIPE is suppressed, exit 0 for EPIPE when all outputs finished +read_fifo +yes | timeout 10 tee -p 2>err >fifo || fail=1 +test $(wc -l < err) = 0 || { cat err; fail=1; } + +# With --write-error=warn, exit 1 for EPIPE when all outputs finished +read_fifo +yes | returns_ 1 timeout 10 tee --write-error=warn 2>err >fifo || fail=1 +test $(wc -l < err) = 1 || { cat err; fail=1; } + +# With --write-error=exit, exit 1 immediately for EPIPE +read_fifo +yes | returns_ 1 timeout 10 tee --write-error=exit /dev/null 2>err >fifo \ + || fail=1 +test $(wc -l < err) = 1 || { cat err; fail=1; } + +# With --write-error=exit-nopipe, exit 0 for EPIPE +read_fifo +yes | timeout 10 tee --write-error=exit-nopipe 2>err >fifo || fail=1 +test $(wc -l < err) = 0 || { cat err; fail=1; } + +wait Exit $fail |