diff --git a/pkg/goanalysis/runner.go b/pkg/goanalysis/runner.go index 16b4e5a50e83..ba9c0bd0664c 100644 --- a/pkg/goanalysis/runner.go +++ b/pkg/goanalysis/runner.go @@ -5,6 +5,7 @@ package goanalysis import ( + "context" "encoding/gob" "fmt" "go/token" @@ -259,10 +260,12 @@ func (r *runner) analyze(pkgs []*packages.Package, analyzers []*analysis.Analyze debugf("Analyzing at most %d packages in parallel", gomaxprocs) loadSem := make(chan struct{}, gomaxprocs) - stopChan := make(chan struct{}, 1) debugf("There are %d initial and %d total packages", len(initialPkgs), len(loadingPackages)) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var wg sync.WaitGroup for _, lp := range loadingPackages { @@ -270,7 +273,7 @@ func (r *runner) analyze(pkgs []*packages.Package, analyzers []*analysis.Analyze wg.Add(1) go func(lp *loadingPackage) { - lp.analyzeRecursive(stopChan, r.loadMode, loadSem) + lp.analyzeRecursive(ctx, cancel, r.loadMode, loadSem) wg.Done() }(lp) diff --git a/pkg/goanalysis/runner_action.go b/pkg/goanalysis/runner_action.go index c25324b7783e..eafc2e4d88c9 100644 --- a/pkg/goanalysis/runner_action.go +++ b/pkg/goanalysis/runner_action.go @@ -29,12 +29,10 @@ func (actAlloc *actionAllocator) alloc() *action { return act } -func (act *action) waitUntilDependingAnalyzersWorked(ctx context.Context, stopChan chan struct{}) { +func (act *action) waitUntilDependingAnalyzersWorked(ctx context.Context) { for _, dep := range act.Deps { if dep.Package == act.Package { select { - case <-stopChan: - return case <-ctx.Done(): return case <-dep.analysisDoneCh: diff --git a/pkg/goanalysis/runner_loadingpackage.go b/pkg/goanalysis/runner_loadingpackage.go index 001b80060b0b..29a27089c1c2 100644 --- a/pkg/goanalysis/runner_loadingpackage.go +++ b/pkg/goanalysis/runner_loadingpackage.go @@ -41,7 +41,7 @@ type loadingPackage struct { decUseMutex sync.Mutex } -func (lp *loadingPackage) analyzeRecursive(stopChan chan struct{}, loadMode LoadMode, loadSem chan struct{}) { +func (lp *loadingPackage) analyzeRecursive(ctx context.Context, cancel context.CancelFunc, loadMode LoadMode, loadSem chan struct{}) { lp.analyzeOnce.Do(func() { // Load the direct dependencies, in parallel. var wg sync.WaitGroup @@ -50,7 +50,7 @@ func (lp *loadingPackage) analyzeRecursive(stopChan chan struct{}, loadMode Load for _, imp := range lp.imports { go func(imp *loadingPackage) { - imp.analyzeRecursive(stopChan, loadMode, loadSem) + imp.analyzeRecursive(ctx, cancel, loadMode, loadSem) wg.Done() }(imp) @@ -58,16 +58,22 @@ func (lp *loadingPackage) analyzeRecursive(stopChan chan struct{}, loadMode Load wg.Wait() - lp.analyze(stopChan, loadMode, loadSem) + lp.analyze(ctx, cancel, loadMode, loadSem) }) } -func (lp *loadingPackage) analyze(stopChan chan struct{}, loadMode LoadMode, loadSem chan struct{}) { +func (lp *loadingPackage) analyze(ctx context.Context, cancel context.CancelFunc, loadMode LoadMode, loadSem chan struct{}) { loadSem <- struct{}{} defer func() { <-loadSem }() + select { + case <-ctx.Done(): + return + default: + } + // Save memory on unused more fields. defer lp.decUse(loadMode < LoadModeWholeProgram) @@ -85,16 +91,14 @@ func (lp *loadingPackage) analyze(stopChan chan struct{}, loadMode LoadMode, loa return } - actsWg, ctx := errgroup.WithContext(context.Background()) + actsWg, ctxGroup := errgroup.WithContext(ctx) for _, act := range lp.actions { actsWg.Go(func() error { - act.waitUntilDependingAnalyzersWorked(ctx, stopChan) + act.waitUntilDependingAnalyzersWorked(ctxGroup) select { - case <-stopChan: - return nil - case <-ctx.Done(): + case <-ctxGroup.Done(): return nil default: } @@ -107,7 +111,7 @@ func (lp *loadingPackage) analyze(stopChan chan struct{}, loadMode LoadMode, loa err := actsWg.Wait() if err != nil { - close(stopChan) + cancel() } }