From 0f64a49460974fa65292d8d5bf6c8a9ceca4b780 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 5 Oct 2022 14:04:55 -0400 Subject: os/exec: remove protection against a duplicate Close on StdinPipe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As of CL 438347, multiple concurrents calls to Close should be safe. This removes some indirection and may also make some programs that use type-assertions marginally more efficient. For example, if a program calls (*exec.Cmd).StdinPipe to obtain a pipe and then sets that as the Stdout of another command, that program will now allow the second command to inherit the file descriptor directly instead of copying everything through a goroutine. This will also cause calls to Close after the first to return an error wrapping os.ErrClosed instead of nil. However, it seems unlikely that programs will depend on that error behavior: if a program is calling Write in a loop followed by Close, then if a racing Close occurs it is likely that the Write would have already reported an error. (The only programs likely to notice a change are those that call Close — without Write! — after a call to Wait.) Updates #56043. Updates #9307. Updates #6270. Change-Id: Iec734b23acefcc7e7ad0c8bc720085bc45988efb Reviewed-on: https://go-review.googlesource.com/c/go/+/439195 Reviewed-by: Ian Lance Taylor Auto-Submit: Bryan Mills Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot --- src/os/exec/exec.go | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) (limited to 'src/os/exec/exec.go') diff --git a/src/os/exec/exec.go b/src/os/exec/exec.go index aa601b6ccc..0d7a86bad4 100644 --- a/src/os/exec/exec.go +++ b/src/os/exec/exec.go @@ -102,7 +102,6 @@ import ( "runtime" "strconv" "strings" - "sync" "syscall" ) @@ -809,25 +808,8 @@ func (c *Cmd) StdinPipe() (io.WriteCloser, error) { } c.Stdin = pr c.childIOFiles = append(c.childIOFiles, pr) - wc := &closeOnce{File: pw} - c.parentIOPipes = append(c.parentIOPipes, wc) - return wc, nil -} - -type closeOnce struct { - *os.File - - once sync.Once - err error -} - -func (c *closeOnce) Close() error { - c.once.Do(c.close) - return c.err -} - -func (c *closeOnce) close() { - c.err = c.File.Close() + c.parentIOPipes = append(c.parentIOPipes, pw) + return pw, nil } // StdoutPipe returns a pipe that will be connected to the command's -- cgit v1.3