Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-Zero Exit Status Does Not Propagate using Exec().Filter() #148

Closed
jesselang opened this issue Dec 2, 2022 · 2 comments
Closed

Non-Zero Exit Status Does Not Propagate using Exec().Filter() #148

jesselang opened this issue Dec 2, 2022 · 2 comments

Comments

@jesselang
Copy link
Contributor

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!

@bitfield
Copy link
Owner

bitfield commented Dec 7, 2022

This was a good find, @jesselang: there are (at least) two distinct bugs here:

  1. The new pipe created by Filter takes no account of the original pipe's error status. In other words, if you call Filter on a pipe whose error status is set, that error is lost, as you showed.
  2. The return value of the Filterfunction always overwrites any previous error, even when it's nil. So if it is nil, 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?

@jesselang
Copy link
Contributor Author

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants