packer: fix data race in communicator
This commit is contained in:
parent
32ab55c79f
commit
4524b13911
|
@ -33,9 +33,11 @@ type RemoteCmd struct {
|
||||||
// Once Exited is true, this will contain the exit code of the process.
|
// Once Exited is true, this will contain the exit code of the process.
|
||||||
ExitStatus int
|
ExitStatus int
|
||||||
|
|
||||||
// Internal locks and such used for safely setting some shared variables
|
// Internal fields
|
||||||
l sync.Mutex
|
|
||||||
exitCh chan struct{}
|
exitCh chan struct{}
|
||||||
|
|
||||||
|
// This thing is a mutex, lock when making modifications concurrently
|
||||||
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Communicator is the interface used to communicate with the machine
|
// A Communicator is the interface used to communicate with the machine
|
||||||
|
@ -76,6 +78,9 @@ func (r *RemoteCmd) StartWithUi(c Communicator, ui Ui) error {
|
||||||
originalStdout := r.Stdout
|
originalStdout := r.Stdout
|
||||||
originalStderr := r.Stderr
|
originalStderr := r.Stderr
|
||||||
defer func() {
|
defer func() {
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
|
||||||
r.Stdout = originalStdout
|
r.Stdout = originalStdout
|
||||||
r.Stderr = originalStderr
|
r.Stderr = originalStderr
|
||||||
}()
|
}()
|
||||||
|
@ -141,8 +146,8 @@ OutputLoop:
|
||||||
// should be called by communicators who are running a remote command in
|
// should be called by communicators who are running a remote command in
|
||||||
// order to set that the command is done.
|
// order to set that the command is done.
|
||||||
func (r *RemoteCmd) SetExited(status int) {
|
func (r *RemoteCmd) SetExited(status int) {
|
||||||
r.l.Lock()
|
r.Lock()
|
||||||
defer r.l.Unlock()
|
defer r.Unlock()
|
||||||
|
|
||||||
if r.exitCh == nil {
|
if r.exitCh == nil {
|
||||||
r.exitCh = make(chan struct{})
|
r.exitCh = make(chan struct{})
|
||||||
|
@ -156,11 +161,11 @@ func (r *RemoteCmd) SetExited(status int) {
|
||||||
// Wait waits for the remote command to complete.
|
// Wait waits for the remote command to complete.
|
||||||
func (r *RemoteCmd) Wait() {
|
func (r *RemoteCmd) Wait() {
|
||||||
// Make sure our condition variable is initialized.
|
// Make sure our condition variable is initialized.
|
||||||
r.l.Lock()
|
r.Lock()
|
||||||
if r.exitCh == nil {
|
if r.exitCh == nil {
|
||||||
r.exitCh = make(chan struct{})
|
r.exitCh = make(chan struct{})
|
||||||
}
|
}
|
||||||
r.l.Unlock()
|
r.Unlock()
|
||||||
|
|
||||||
<-r.exitCh
|
<-r.exitCh
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,9 @@ type TestCommunicator struct {
|
||||||
|
|
||||||
func (c *TestCommunicator) Start(rc *RemoteCmd) error {
|
func (c *TestCommunicator) Start(rc *RemoteCmd) error {
|
||||||
go func() {
|
go func() {
|
||||||
|
rc.Lock()
|
||||||
|
defer rc.Unlock()
|
||||||
|
|
||||||
if rc.Stdout != nil && c.Stdout != nil {
|
if rc.Stdout != nil && c.Stdout != nil {
|
||||||
io.Copy(rc.Stdout, c.Stdout)
|
io.Copy(rc.Stdout, c.Stdout)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue