aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing/transport/file
diff options
context:
space:
mode:
authorSantiago M. Mola <santi@mola.io>2017-07-07 11:10:37 +0200
committerSantiago M. Mola <santi@mola.io>2017-07-07 11:10:37 +0200
commit6506d377f7dc70b72d7454f5901d8199023dd8ed (patch)
tree96dacfe133ae23d5c200b62c78dcd16306c3a7f6 /plumbing/transport/file
parent22d8c7082f547acdc245fd836c1962583c0c87a1 (diff)
downloadgo-git-6506d377f7dc70b72d7454f5901d8199023dd8ed.tar.gz
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().
Diffstat (limited to 'plumbing/transport/file')
-rw-r--r--plumbing/transport/file/client.go18
1 files changed, 14 insertions, 4 deletions
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