From b7d9eb04f4c510213e29f46db7eab4ec5c72a4ae Mon Sep 17 00:00:00 2001 From: Joey Jiao Date: Mon, 13 May 2024 12:51:49 +0800 Subject: pkg/cover: fix concurrent append to slice It's not safe to append to slice from multiple goroutines. Either using chan or lock can get constant result. --- pkg/cover/backend/dwarf.go | 50 +++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/pkg/cover/backend/dwarf.go b/pkg/cover/backend/dwarf.go index 5b2281a36..5378c1cd7 100644 --- a/pkg/cover/backend/dwarf.go +++ b/pkg/cover/backend/dwarf.go @@ -153,9 +153,16 @@ func makeDWARFUnsafe(params *dwarfParams) (*Impl, error) { var allRanges []pcRange var allUnits []*CompileUnit preciseCoverage := true + type binResult struct { + symbols []*Symbol + coverPoints [2][]uint64 + ranges []pcRange + units []*CompileUnit + err error + } + binC := make(chan binResult, len(modules)) for _, module := range modules { - errc := make(chan error, 1) - go func() { + go func(m *Module) { info := &symbolInfo{ tracePC: make(map[uint64]bool), traceCmp: make(map[uint64]bool), @@ -164,31 +171,38 @@ func makeDWARFUnsafe(params *dwarfParams) (*Impl, error) { } result, err := processModule(params, module, info, target) if err != nil { - errc <- err + binC <- binResult{err: err} return } - allSymbols = append(allSymbols, result.Symbols...) - allCoverPoints[0] = append(allCoverPoints[0], result.CoverPoints[0]...) - allCoverPoints[1] = append(allCoverPoints[1], result.CoverPoints[1]...) if module.Name == "" && len(result.CoverPoints[0]) == 0 { err = fmt.Errorf("%v doesn't contain coverage callbacks (set CONFIG_KCOV=y on linux)", module.Path) + if err != nil { + binC <- binResult{err: err} + return + } } - errc <- err - }() - ranges, units, err := params.readTextRanges(module) - if err != nil { - return nil, err - } - if err := <-errc; err != nil { - return nil, err - } - allRanges = append(allRanges, ranges...) - allUnits = append(allUnits, units...) + ranges, units, err := params.readTextRanges(module) + if err != nil { + binC <- binResult{err: err} + return + } + binC <- binResult{symbols: result.Symbols, coverPoints: result.CoverPoints, ranges: ranges, units: units} + }(module) if isKcovBrokenInCompiler(params.getCompilerVersion(module.Path)) { preciseCoverage = false } } - + for range modules { + result := <-binC + if err := result.err; err != nil { + return nil, err + } + allSymbols = append(allSymbols, result.symbols...) + allCoverPoints[0] = append(allCoverPoints[0], result.coverPoints[0]...) + allCoverPoints[1] = append(allCoverPoints[1], result.coverPoints[1]...) + allRanges = append(allRanges, result.ranges...) + allUnits = append(allUnits, result.units...) + } sort.Slice(allSymbols, func(i, j int) bool { return allSymbols[i].Start < allSymbols[j].Start }) -- cgit mrf-deployment