You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Pipeline: suppress pipe errors in some circumstances
Consider a pipeline
p := pipe.New()
p.Add(s1, s2, s3, s4)
Suppose that stage `s3` sometimes intentionally exits early without
reading all of its `stdin`. When this happens, it is common for the
previous stage `s2` to fail with a pipe error. This is because `s2`
often continues trying to write to its stdout, but the other end of
its stdout is `s3`'s stdin, which got closed when `s3` exited. The
result is that `s2` fails with `SIGPIPE`, `syscall.EPIPE`, or
`io.ErrClosedPipe`.
But if it is expected that `s3` exits early, then a pipe error from
`s2` is uninteresting. The current way of dealing with this situation
is to explicitly wrap `s2` with something like `pipe.IgnoreError(s2,
IsPipeError)`, which causes a pipe error from that stage to be
ignored. But often that's not the end of the story. If `s2` exits due
to a pipe error, then it is often the case that `s1` will _also_ exit
due to a pipe error trying to write to _its_ stdout. So to handle this
situation correctly, the pipe would have to be created like
p := pipe.New()
p.Add(
pipe.IgnoreError(s1, IsPipeError),
pipe.IgnoreError(s2, IsPipeError),
s3,
s4,
)
This is verbose, and experience shows that it is easy to forget. Let's
make this simpler.
If `s3` intentionally exits without reading all of its input, it
should return the special `FinishEarly` error, thereby telling the
enclosing pipeline that its early exit was intentional. In this case,
change `Pipeline` to ignore any pipe error from the preceding stage,
`s2`. Moreover, if `s2` exits with a pipe error, ignore any pipe error
from `s1`, and so on. However, if a stage exits without an error, then
again consider a pipe error from the previous stage to be interesting.
There is some chance that this could suppress actual, interesting
errors. For example, `s2` might exit due to a `SIGPIPE` that it got
when trying to write to a file descriptor other than stdout, for
example when writing to a subprocess or to a socket, and not handle
that `EPIPE` internally. But I think that these situations will be
vanishingly rare compared to the more common case described above,
which has caused real-life irritation.
Also add tests of the new behavior.
0 commit comments