depgraph: fix data races
This commit is contained in:
parent
d970cec8eb
commit
bce5d55a85
|
@ -9,6 +9,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/digraph"
|
"github.com/hashicorp/terraform/digraph"
|
||||||
)
|
)
|
||||||
|
@ -217,6 +218,7 @@ CHECK_CYCLES:
|
||||||
// then introduce a lock in your callback.
|
// then introduce a lock in your callback.
|
||||||
func (g *Graph) Walk(fn WalkFunc) error {
|
func (g *Graph) Walk(fn WalkFunc) error {
|
||||||
// Set so we don't callback for a single noun multiple times
|
// Set so we don't callback for a single noun multiple times
|
||||||
|
var seenMapL sync.RWMutex
|
||||||
seenMap := make(map[*Noun]chan struct{})
|
seenMap := make(map[*Noun]chan struct{})
|
||||||
seenMap[g.Root] = make(chan struct{})
|
seenMap[g.Root] = make(chan struct{})
|
||||||
|
|
||||||
|
@ -236,7 +238,9 @@ func (g *Graph) Walk(fn WalkFunc) error {
|
||||||
// Go through each dependency and run that first
|
// Go through each dependency and run that first
|
||||||
for _, dep := range current.Deps {
|
for _, dep := range current.Deps {
|
||||||
if _, ok := seenMap[dep.Target]; !ok {
|
if _, ok := seenMap[dep.Target]; !ok {
|
||||||
|
seenMapL.Lock()
|
||||||
seenMap[dep.Target] = make(chan struct{})
|
seenMap[dep.Target] = make(chan struct{})
|
||||||
|
seenMapL.Unlock()
|
||||||
tovisit = append(tovisit, dep.Target)
|
tovisit = append(tovisit, dep.Target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,12 +248,20 @@ func (g *Graph) Walk(fn WalkFunc) error {
|
||||||
// Spawn off a goroutine to execute our callback once
|
// Spawn off a goroutine to execute our callback once
|
||||||
// all our dependencies are satisified.
|
// all our dependencies are satisified.
|
||||||
go func(current *Noun) {
|
go func(current *Noun) {
|
||||||
defer close(seenMap[current])
|
seenMapL.RLock()
|
||||||
|
closeCh := seenMap[current]
|
||||||
|
seenMapL.RUnlock()
|
||||||
|
|
||||||
|
defer close(closeCh)
|
||||||
|
|
||||||
// Wait for all our dependencies
|
// Wait for all our dependencies
|
||||||
for _, dep := range current.Deps {
|
for _, dep := range current.Deps {
|
||||||
|
seenMapL.RLock()
|
||||||
|
ch := seenMap[dep.Target]
|
||||||
|
seenMapL.RUnlock()
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-seenMap[dep.Target]:
|
case <-ch:
|
||||||
case <-quitCh:
|
case <-quitCh:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue