core: dag errors should cascade to all descendents

We weren't marking skipped nodes as failing, so any
grandchild-and-deeper dependencies would still evaluate.

For example:

    A -> B -> C -> D

If B failed, C would be skipped, but D would still be evaluated.

This fixes the behavior so C, D, and any further descendents will all be
skipped when B fails.

Addresses crashing aspect of #2955 and likely a lot of other confusing
failure modes.
This commit is contained in:
Paul Hinze 2015-08-07 11:20:13 -05:00
parent f238e254f4
commit baa33d7326
2 changed files with 6 additions and 3 deletions

View File

@ -195,7 +195,7 @@ func (g *AcyclicGraph) Walk(cb WalkFunc) error {
// Start the goroutine to wait for our dependencies // Start the goroutine to wait for our dependencies
readyCh := make(chan bool) readyCh := make(chan bool)
go func(deps []Vertex, chs []<-chan struct{}, readyCh chan<- bool) { go func(v Vertex, deps []Vertex, chs []<-chan struct{}, readyCh chan<- bool) {
// First wait for all the dependencies // First wait for all the dependencies
for _, ch := range chs { for _, ch := range chs {
<-ch <-ch
@ -206,13 +206,14 @@ func (g *AcyclicGraph) Walk(cb WalkFunc) error {
defer errLock.Unlock() defer errLock.Unlock()
for _, dep := range deps { for _, dep := range deps {
if errMap[dep] { if errMap[dep] {
errMap[v] = true
readyCh <- false readyCh <- false
return return
} }
} }
readyCh <- true readyCh <- true
}(deps, depChs, readyCh) }(v, deps, depChs, readyCh)
// Start the goroutine that executes // Start the goroutine that executes
go func(v Vertex, doneCh chan<- struct{}, readyCh <-chan bool) { go func(v Vertex, doneCh chan<- struct{}, readyCh <-chan bool) {

View File

@ -226,8 +226,10 @@ func TestAcyclicGraphWalk_error(t *testing.T) {
g.Add(1) g.Add(1)
g.Add(2) g.Add(2)
g.Add(3) g.Add(3)
g.Add(4)
g.Connect(BasicEdge(4, 3))
g.Connect(BasicEdge(3, 2)) g.Connect(BasicEdge(3, 2))
g.Connect(BasicEdge(3, 1)) g.Connect(BasicEdge(2, 1))
var visits []Vertex var visits []Vertex
var lock sync.Mutex var lock sync.Mutex