Skip to content

Commit

Permalink
Terminate on elimination of all writers in tee
Browse files Browse the repository at this point in the history
tee is supposed to exit when there is nothing left to write to. For
finite inputs, it can be hard to determine whether this functions
correctly, but for tee of infinite streams, it is very important to
exit when there is nothing more to write to.
  • Loading branch information
eds-collabora committed Jun 25, 2022
1 parent 953dd57 commit b26700f
Showing 1 changed file with 17 additions and 4 deletions.
21 changes: 17 additions & 4 deletions src/uu/tee/src/tee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,18 @@ fn tee(options: &Options) -> Result<()> {
inner: Box::new(stdin()) as Box<dyn Read>,
};

// TODO: replaced generic 'copy' call to be able to stop copying
// if all outputs are closed (due to errors)
if copy(input, &mut output).is_err() || output.flush().is_err() || output.error_occurred() {
Err(Error::new(ErrorKind::Other, ""))
let res = match copy(input, &mut output) {
// ErrorKind::Other is raised by MultiWriter when all writers
// have exited, so that copy will abort. It's equivalent to
// success of this part (if there was an error that should
// cause a failure from any writer, that error would have been
// returned instead).
Err(e) if e.kind() != ErrorKind::Other => Err(e),
_ => Ok(()),
};

if res.is_err() || output.flush().is_err() || output.error_occurred() {
Err(Error::from(ErrorKind::Other))
} else {
Ok(())
}
Expand Down Expand Up @@ -313,6 +321,11 @@ impl Write for MultiWriter {
self.ignored_errors += errors;
if let Some(e) = aborted {
Err(e)
} else if self.writers.is_empty() {
// This error kind will never be raised by the standard
// library, so we can use it for early termination of
// `copy`
Err(Error::from(ErrorKind::Other))
} else {
Ok(buf.len())
}
Expand Down

0 comments on commit b26700f

Please sign in to comment.