Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 6506d37

Browse files
committed
transport/file: avoid race with Command.Wait, fixes #463
Pipe returned by Command.StderrPipe() has a race with Read and Command.Wait(). We use a io.Pipe() instead and ensure it is closed after Wait().
1 parent 22d8c70 commit 6506d37

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed

plumbing/transport/file/client.go

+14-4
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,22 @@ func (r *runner) Command(cmd string, ep transport.Endpoint, auth transport.AuthM
4646
}
4747

4848
type command struct {
49-
cmd *exec.Cmd
50-
closed bool
49+
cmd *exec.Cmd
50+
stderrCloser io.Closer
51+
closed bool
5152
}
5253

5354
func (c *command) Start() error {
5455
return c.cmd.Start()
5556
}
5657

5758
func (c *command) StderrPipe() (io.Reader, error) {
58-
return c.cmd.StderrPipe()
59+
// Pipe returned by Command.StderrPipe has a race with Read + Command.Wait.
60+
// We use an io.Pipe and close it after the command finishes.
61+
r, w := io.Pipe()
62+
c.cmd.Stderr = w
63+
c.stderrCloser = r
64+
return r, nil
5965
}
6066

6167
func (c *command) StdinPipe() (io.WriteCloser, error) {
@@ -72,7 +78,11 @@ func (c *command) Close() error {
7278
return nil
7379
}
7480

75-
defer func() { c.closed = true }()
81+
defer func() {
82+
c.closed = true
83+
_ = c.stderrCloser.Close()
84+
}()
85+
7686
err := c.cmd.Wait()
7787
if _, ok := err.(*os.PathError); ok {
7888
return nil

0 commit comments

Comments
 (0)