Fix top-down resolve re-walking graph too much.
Firing off multiple concurrent walks of the same sub-tree with the same
conditions. Data race meant every walk would proceed. Move the logic to
entry of walk function and compare under lock.
Bug: 255526010
Test: m droid
Test: m out/soong/.intermediates/packages/modules/StatsD/apex/com.android.os.statsd/android_common_com.android.os.statsd_image/NOTICE.html.gz
Change-Id: Ie30edbb2ac9eaa9aa55badfc518d51eaadbb6be6
diff --git a/tools/compliance/policy_resolve.go b/tools/compliance/policy_resolve.go
index 93335a9..c58ed2c 100644
--- a/tools/compliance/policy_resolve.go
+++ b/tools/compliance/policy_resolve.go
@@ -171,42 +171,47 @@
walk = func(fnode *TargetNode, cs LicenseConditionSet, treatAsAggregate bool) {
defer wg.Done()
- mu.Lock()
- fnode.resolution |= conditionsFn(fnode)
- fnode.resolution |= cs
- fnode.pure = treatAsAggregate
- amap[fnode] = struct{}{}
- cs = fnode.resolution
- mu.Unlock()
+ continueWalk := func() bool {
+ mu.Lock()
+ defer mu.Unlock()
+ depcs := fnode.resolution
+ _, alreadyWalked := amap[fnode]
+ if alreadyWalked {
+ if cs.IsEmpty() {
+ return false
+ }
+ if cs.Difference(depcs).IsEmpty() {
+ // no new conditions
+
+ // pure aggregates never need walking a 2nd time with same conditions
+ if treatAsAggregate {
+ return false
+ }
+ // non-aggregates don't need walking as non-aggregate a 2nd time
+ if !fnode.pure {
+ return false
+ }
+ // previously walked as pure aggregate; need to re-walk as non-aggregate
+ }
+ }
+ fnode.resolution |= conditionsFn(fnode)
+ fnode.resolution |= cs
+ fnode.pure = treatAsAggregate
+ amap[fnode] = struct{}{}
+ cs = fnode.resolution
+ return true
+ }()
+ if !continueWalk {
+ return
+ }
// for each dependency
for _, edge := range fnode.edges {
- func(edge *TargetEdge) {
- // dcs holds the dpendency conditions inherited from the target
- dcs := targetConditionsPropagatingToDep(lg, edge, cs, treatAsAggregate, conditionsFn)
- dnode := edge.dependency
- mu.Lock()
- defer mu.Unlock()
- depcs := dnode.resolution
- _, alreadyWalked := amap[dnode]
- if !dcs.IsEmpty() && alreadyWalked {
- if dcs.Difference(depcs).IsEmpty() {
- // no new conditions
-
- // pure aggregates never need walking a 2nd time with same conditions
- if treatAsAggregate {
- return
- }
- // non-aggregates don't need walking as non-aggregate a 2nd time
- if !dnode.pure {
- return
- }
- // previously walked as pure aggregate; need to re-walk as non-aggregate
- }
- }
- // add the conditions to the dependency
- wg.Add(1)
- go walk(dnode, dcs, treatAsAggregate && dnode.IsContainer())
- }(edge)
+ // dcs holds the dpendency conditions inherited from the target
+ dcs := targetConditionsPropagatingToDep(lg, edge, cs, treatAsAggregate, conditionsFn)
+ dnode := edge.dependency
+ // add the conditions to the dependency
+ wg.Add(1)
+ go walk(dnode, dcs, treatAsAggregate && dnode.IsContainer())
}
}