Non-Zero Exit Status Does Not Propagate using Exec().Filter()
jesselang opened this issue · 2 comments
From #146:
An undesired side effect of using Exec().Filter*() seems to be that a non-zero exit status from the program no longer propagates. Here's an example:
package main
import (
"fmt"
"io"
"github.com/bitfield/script"
)
func main() {
p := script.Exec("false")
_, err := p.Stdout()
fmt.Printf("%d %v\n", p.ExitStatus(), err)
p = script.Exec("false").Filter(func(r io.Reader, w io.Writer) error {
_, err := io.Copy(w, r)
return err
})
_, err = p.Stdout()
fmt.Printf("%d %v\n", p.ExitStatus(), err)
}Output:
1 exit status 1
0 <nil>
Is this expected? I'd prefer to pass the exit status to the caller of this script. Thanks!
This was a good find, @jesselang: there are (at least) two distinct bugs here:
- The new pipe created by
Filtertakes no account of the original pipe's error status. In other words, if you callFilteron a pipe whose error status is set, that error is lost, as you showed. - The return value of the
Filterfunction always overwrites any previous error, even when it'snil. So if it isnil, then a previous error is wiped out.
Also, because the Exec command runs in a goroutine, it's racing with the Filter func. If the command completes and sets the error status before the Filter func starts, then Filter becomes a no-op, like any other pipe stage, so the command's exit status is preserved. If the Filter func has already started before the command exits, then whatever error status the command sets on the pipe is too late to make the Filter a no-op.
So your program sometimes printed:
0 <nil>
and sometimes:
1 exit status 1
depending on the local cosmic ray environment.
828fe5f fixes the first issue; d5e838d fixes the second. With, and only with, both bugs fixed, your program now reliably reports 1 exit status 1, even under high radiation flux. Would you mind confirming it works for you with v0.21.4?
Wow, seems I tripped over more than I realized! Yes, I am able to confirm that v0.21.4 does reliably pass along the pipe's exit status. Thank you very much!