1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

Terminate on elimination of all writers in tee

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.
This commit is contained in:
Ed Smith 2022-06-25 23:19:30 +01:00 committed by Sylvestre Ledru
parent 5c13e88f8b
commit 607bf3ca4d

View file

@ -199,10 +199,18 @@ fn tee(options: &Options) -> Result<()> {
inner: Box::new(stdin()) as Box<dyn Read>, inner: Box::new(stdin()) as Box<dyn Read>,
}; };
// TODO: replaced generic 'copy' call to be able to stop copying let res = match copy(input, &mut output) {
// if all outputs are closed (due to errors) // ErrorKind::Other is raised by MultiWriter when all writers
if copy(input, &mut output).is_err() || output.flush().is_err() || output.error_occurred() { // have exited, so that copy will abort. It's equivalent to
Err(Error::new(ErrorKind::Other, "")) // 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 { } else {
Ok(()) Ok(())
} }
@ -313,6 +321,11 @@ impl Write for MultiWriter {
self.ignored_errors += errors; self.ignored_errors += errors;
if let Some(e) = aborted { if let Some(e) = aborted {
Err(e) 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 { } else {
Ok(buf.len()) Ok(buf.len())
} }