@@ -39,23 +39,28 @@ type loadingPackage struct {
39
39
decUseMutex sync.Mutex
40
40
}
41
41
42
- func (lp * loadingPackage ) analyzeRecursive (loadMode LoadMode , loadSem chan struct {}) {
42
+ func (lp * loadingPackage ) analyzeRecursive (stopChan chan struct {}, loadMode LoadMode , loadSem chan struct {}) {
43
43
lp .analyzeOnce .Do (func () {
44
44
// Load the direct dependencies, in parallel.
45
45
var wg sync.WaitGroup
46
+
46
47
wg .Add (len (lp .imports ))
48
+
47
49
for _ , imp := range lp .imports {
48
50
go func (imp * loadingPackage ) {
49
- imp .analyzeRecursive (loadMode , loadSem )
51
+ imp .analyzeRecursive (stopChan , loadMode , loadSem )
52
+
50
53
wg .Done ()
51
54
}(imp )
52
55
}
56
+
53
57
wg .Wait ()
54
- lp .analyze (loadMode , loadSem )
58
+
59
+ lp .analyze (stopChan , loadMode , loadSem )
55
60
})
56
61
}
57
62
58
- func (lp * loadingPackage ) analyze (loadMode LoadMode , loadSem chan struct {}) {
63
+ func (lp * loadingPackage ) analyze (stopChan chan struct {}, loadMode LoadMode , loadSem chan struct {}) {
59
64
loadSem <- struct {}{}
60
65
defer func () {
61
66
<- loadSem
@@ -65,27 +70,46 @@ func (lp *loadingPackage) analyze(loadMode LoadMode, loadSem chan struct{}) {
65
70
defer lp .decUse (loadMode < LoadModeWholeProgram )
66
71
67
72
if err := lp .loadWithFacts (loadMode ); err != nil {
68
- werr := fmt .Errorf ("failed to load package %s: %w" , lp .pkg .Name , err )
69
73
// Don't need to write error to errCh, it will be extracted and reported on another layer.
70
74
// Unblock depending on actions and propagate error.
71
75
for _ , act := range lp .actions {
72
76
close (act .analysisDoneCh )
73
- act .Err = werr
77
+
78
+ act .Err = fmt .Errorf ("failed to load package %s: %w" , lp .pkg .Name , err )
74
79
}
80
+
75
81
return
76
82
}
77
83
78
84
var actsWg sync.WaitGroup
85
+
79
86
actsWg .Add (len (lp .actions ))
87
+
80
88
for _ , act := range lp .actions {
81
89
go func (act * action ) {
82
90
defer actsWg .Done ()
83
91
84
- act .waitUntilDependingAnalyzersWorked ()
92
+ act .waitUntilDependingAnalyzersWorked (stopChan )
93
+
94
+ select {
95
+ case <- stopChan :
96
+ return
97
+ default :
98
+ }
85
99
86
100
act .analyzeSafe ()
101
+
102
+ select {
103
+ case <- stopChan :
104
+ return
105
+ default :
106
+ if act .Err != nil {
107
+ close (stopChan )
108
+ }
109
+ }
87
110
}(act )
88
111
}
112
+
89
113
actsWg .Wait ()
90
114
}
91
115
0 commit comments