From 6506d377f7dc70b72d7454f5901d8199023dd8ed Mon Sep 17 00:00:00 2001 From: "Santiago M. Mola" Date: Fri, 7 Jul 2017 11:10:37 +0200 Subject: 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(). --- plumbing/transport/file/client.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'plumbing') diff --git a/plumbing/transport/file/client.go b/plumbing/transport/file/client.go index a199b01..b6d60c1 100644 --- a/plumbing/transport/file/client.go +++ b/plumbing/transport/file/client.go @@ -46,8 +46,9 @@ func (r *runner) Command(cmd string, ep transport.Endpoint, auth transport.AuthM } type command struct { - cmd *exec.Cmd - closed bool + cmd *exec.Cmd + stderrCloser io.Closer + closed bool } func (c *command) Start() error { @@ -55,7 +56,12 @@ func (c *command) Start() error { } func (c *command) StderrPipe() (io.Reader, error) { - return c.cmd.StderrPipe() + // Pipe returned by Command.StderrPipe has a race with Read + Command.Wait. + // We use an io.Pipe and close it after the command finishes. + r, w := io.Pipe() + c.cmd.Stderr = w + c.stderrCloser = r + return r, nil } func (c *command) StdinPipe() (io.WriteCloser, error) { @@ -72,7 +78,11 @@ func (c *command) Close() error { return nil } - defer func() { c.closed = true }() + defer func() { + c.closed = true + _ = c.stderrCloser.Close() + }() + err := c.cmd.Wait() if _, ok := err.(*os.PathError); ok { return nil -- cgit