diff --git a/go.mod b/go.mod index 910cf3bac2b3..d44875f075cd 100644 --- a/go.mod +++ b/go.mod @@ -134,6 +134,7 @@ require ( go.augendre.info/fatcontext v0.8.0 go.uber.org/automaxprocs v1.6.0 golang.org/x/mod v0.26.0 + golang.org/x/sync v0.15.0 golang.org/x/sys v0.34.0 golang.org/x/tools v0.34.0 gopkg.in/yaml.v3 v3.0.1 @@ -213,7 +214,6 @@ require ( go.uber.org/zap v1.24.0 // indirect golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/sync v0.15.0 // indirect golang.org/x/text v0.26.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/pkg/goanalysis/runner_action.go b/pkg/goanalysis/runner_action.go index 855b769bcc99..c25324b7783e 100644 --- a/pkg/goanalysis/runner_action.go +++ b/pkg/goanalysis/runner_action.go @@ -1,6 +1,7 @@ package goanalysis import ( + "context" "fmt" "runtime/debug" @@ -28,12 +29,14 @@ func (actAlloc *actionAllocator) alloc() *action { return act } -func (act *action) waitUntilDependingAnalyzersWorked(stopChan chan struct{}) { +func (act *action) waitUntilDependingAnalyzersWorked(ctx context.Context, stopChan chan struct{}) { 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 cb0dcd000516..001b80060b0b 100644 --- a/pkg/goanalysis/runner_loadingpackage.go +++ b/pkg/goanalysis/runner_loadingpackage.go @@ -1,6 +1,7 @@ package goanalysis import ( + "context" "errors" "fmt" "go/ast" @@ -14,6 +15,7 @@ import ( "sync" "sync/atomic" + "golang.org/x/sync/errgroup" "golang.org/x/tools/go/gcexportdata" "golang.org/x/tools/go/packages" @@ -83,36 +85,30 @@ func (lp *loadingPackage) analyze(stopChan chan struct{}, loadMode LoadMode, loa return } - var actsWg sync.WaitGroup - - actsWg.Add(len(lp.actions)) + actsWg, ctx := errgroup.WithContext(context.Background()) for _, act := range lp.actions { - go func(act *action) { - defer actsWg.Done() - - act.waitUntilDependingAnalyzersWorked(stopChan) + actsWg.Go(func() error { + act.waitUntilDependingAnalyzersWorked(ctx, stopChan) select { case <-stopChan: - return + return nil + case <-ctx.Done(): + return nil default: } act.analyzeSafe() - select { - case <-stopChan: - return - default: - if act.Err != nil { - close(stopChan) - } - } - }(act) + return act.Err + }) } - actsWg.Wait() + err := actsWg.Wait() + if err != nil { + close(stopChan) + } } func (lp *loadingPackage) loadFromSource(loadMode LoadMode) error {