From 9cbaacad3264028f767b438a98c6f2f12098f3ef Mon Sep 17 00:00:00 2001 From: Paul Hinze Date: Sat, 16 Jan 2016 13:33:24 -0500 Subject: [PATCH] communicator/winrm: fix data race in io copy As the command completes, the winrm.Command does not wait for its copy of the remote.Command streams to report itself completed. This adds an additional sync.WaitGroup to ensure that copy is finished up before moving on, solving the data race. Fixes the following data race: ``` ================== WARNING: DATA RACE Read by goroutine 6: github.com/hashicorp/terraform/communicator/winrm.TestStart() /Users/phinze/go/src/github.com/hashicorp/terraform/communicator/winrm/communicator_test.go:79 +0xa44 testing.tRunner() /private/var/folders/vd/7l9ys5k57l91x63sh28wl_kc0000gn/T/workdir/go/src/testing/testing.go:456 +0xdc Previous write by goroutine 14: bytes.(*Buffer).ReadFrom() /private/var/folders/vd/7l9ys5k57l91x63sh28wl_kc0000gn/T/workdir/go/src/bytes/buffer.go:174 +0x465 io.copyBuffer() /private/var/folders/vd/7l9ys5k57l91x63sh28wl_kc0000gn/T/workdir/go/src/io/io.go:375 +0x1a5 io.Copy() /private/var/folders/vd/7l9ys5k57l91x63sh28wl_kc0000gn/T/workdir/go/src/io/io.go:351 +0x78 Goroutine 6 (running) created at: testing.RunTests() /private/var/folders/vd/7l9ys5k57l91x63sh28wl_kc0000gn/T/workdir/go/src/testing/testing.go:561 +0xaa3 testing.(*M).Run() /private/var/folders/vd/7l9ys5k57l91x63sh28wl_kc0000gn/T/workdir/go/src/testing/testing.go:494 +0xe4 main.main() github.com/hashicorp/terraform/communicator/winrm/_test/_testmain.go:62 +0x20f Goroutine 14 (finished) created at: github.com/hashicorp/terraform/communicator/winrm.runCommand() /Users/phinze/go/src/github.com/hashicorp/terraform/communicator/winrm/communicator.go:151 +0xf8 ================== ``` --- communicator/winrm/communicator.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/communicator/winrm/communicator.go b/communicator/winrm/communicator.go index 27ba31a83..30998e0b1 100644 --- a/communicator/winrm/communicator.go +++ b/communicator/winrm/communicator.go @@ -7,6 +7,7 @@ import ( "math/rand" "strconv" "strings" + "sync" "time" "github.com/hashicorp/terraform/communicator/remote" @@ -148,10 +149,20 @@ func (c *Communicator) Start(rc *remote.Cmd) error { func runCommand(shell *winrm.Shell, cmd *winrm.Command, rc *remote.Cmd) { defer shell.Close() - go io.Copy(rc.Stdout, cmd.Stdout) - go io.Copy(rc.Stderr, cmd.Stderr) + var wg sync.WaitGroup + go func() { + wg.Add(1) + io.Copy(rc.Stdout, cmd.Stdout) + wg.Done() + }() + go func() { + wg.Add(1) + io.Copy(rc.Stderr, cmd.Stderr) + wg.Done() + }() cmd.Wait() + wg.Wait() rc.SetExited(cmd.ExitCode()) }