aboutsummaryrefslogtreecommitdiff
path: root/src/os/exec
diff options
context:
space:
mode:
Diffstat (limited to 'src/os/exec')
-rw-r--r--src/os/exec/exec.go7
-rw-r--r--src/os/exec/exec_test.go26
2 files changed, 33 insertions, 0 deletions
diff --git a/src/os/exec/exec.go b/src/os/exec/exec.go
index a3a0f20ebc..c4c5168b98 100644
--- a/src/os/exec/exec.go
+++ b/src/os/exec/exec.go
@@ -579,6 +579,13 @@ func (c *closeOnce) Write(b []byte) (int, error) {
return n, err
}
+func (c *closeOnce) WriteString(s string) (int, error) {
+ c.writers.RLock()
+ n, err := c.File.WriteString(s)
+ c.writers.RUnlock()
+ return n, err
+}
+
// StdoutPipe returns a pipe that will be connected to the command's
// standard output when the command starts.
//
diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go
index 67fe14faae..d3ac7ab4b9 100644
--- a/src/os/exec/exec_test.go
+++ b/src/os/exec/exec_test.go
@@ -246,6 +246,32 @@ func TestStdinClose(t *testing.T) {
check("Wait", cmd.Wait())
}
+// Issue 17647.
+func TestStdinCloseRace(t *testing.T) {
+ cmd := helperCommand(t, "stdinClose")
+ stdin, err := cmd.StdinPipe()
+ if err != nil {
+ t.Fatalf("StdinPipe: %v", err)
+ }
+ if err := cmd.Start(); err != nil {
+ t.Fatalf("Start: %v", err)
+ }
+ go func() {
+ if err := cmd.Process.Kill(); err != nil {
+ t.Errorf("Kill: %v", err)
+ }
+ }()
+ go func() {
+ io.Copy(stdin, strings.NewReader(stdinCloseTestString))
+ if err := stdin.Close(); err != nil {
+ t.Errorf("stdin.Close: %v", err)
+ }
+ }()
+ if err := cmd.Wait(); err == nil {
+ t.Fatalf("Wait: succeeded unexpectedly")
+ }
+}
+
// Issue 5071
func TestPipeLookPathLeak(t *testing.T) {
fd0, lsof0 := numOpenFDS(t)