aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/os/exec/exec_test.go
diff options
context:
space:
mode:
authorAndrew Gerrand <adg@golang.org>2013-08-29 14:41:44 +1000
committerAndrew Gerrand <adg@golang.org>2013-08-29 14:41:44 +1000
commit10e2ffdf2ca657567fc1708f6387fef69a8445b6 (patch)
treec2644859a14680a2557f5a8628fe800768982c7e /src/pkg/os/exec/exec_test.go
parent466001d05d366cbc97edfb65dc6f5cb883df0498 (diff)
downloadgo-10e2ffdf2ca657567fc1708f6387fef69a8445b6.tar.xz
os/exec: return idempotent Closer from StdinPipe
Before this fix, it was always an error to use the Close method on the io.WriteCloser obtained from Cmd.StdinPipe, as it would race with the Close performed by Cmd.Wait. Fixes #6270. R=golang-dev, r, remyoudompheng, bradfitz, dsymonds CC=golang-dev https://golang.org/cl/13329043
Diffstat (limited to 'src/pkg/os/exec/exec_test.go')
-rw-r--r--src/pkg/os/exec/exec_test.go39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/pkg/os/exec/exec_test.go b/src/pkg/os/exec/exec_test.go
index d7e8573a08..c380d6506c 100644
--- a/src/pkg/os/exec/exec_test.go
+++ b/src/pkg/os/exec/exec_test.go
@@ -152,6 +152,34 @@ func TestPipes(t *testing.T) {
check("Wait", err)
}
+const stdinCloseTestString = "Some test string."
+
+// Issue 6270.
+func TestStdinClose(t *testing.T) {
+ check := func(what string, err error) {
+ if err != nil {
+ t.Fatalf("%s: %v", what, err)
+ }
+ }
+ cmd := helperCommand("stdinClose")
+ stdin, err := cmd.StdinPipe()
+ check("StdinPipe", err)
+ // Check that we can access methods of the underlying os.File.`
+ if _, ok := stdin.(interface {
+ Fd() uintptr
+ }); !ok {
+ t.Error("can't access methods of underlying *os.File")
+ }
+ check("Start", cmd.Start())
+ go func() {
+ _, err := io.Copy(stdin, strings.NewReader(stdinCloseTestString))
+ check("Copy", err)
+ // Before the fix, this next line would race with cmd.Wait.
+ check("Close", stdin.Close())
+ }()
+ check("Wait", cmd.Wait())
+}
+
// Issue 5071
func TestPipeLookPathLeak(t *testing.T) {
fd0 := numOpenFDS(t)
@@ -507,6 +535,17 @@ func TestHelperProcess(*testing.T) {
os.Exit(1)
}
}
+ case "stdinClose":
+ b, err := ioutil.ReadAll(os.Stdin)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error: %v\n", err)
+ os.Exit(1)
+ }
+ if s := string(b); s != stdinCloseTestString {
+ fmt.Fprintf(os.Stderr, "Error: Read %q, want %q", s, stdinCloseTestString)
+ os.Exit(1)
+ }
+ os.Exit(0)
case "read3": // read fd 3
fd3 := os.NewFile(3, "fd3")
bs, err := ioutil.ReadAll(fd3)