aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoey Jiao <quic_jiangenj@quicinc.com>2024-05-13 12:51:49 +0800
committerDmitry Vyukov <dvyukov@google.com>2024-06-11 04:38:10 +0000
commitb7d9eb04f4c510213e29f46db7eab4ec5c72a4ae (patch)
treea53c7bd5a22094c2f4a676e42b6f051984373766
parent08c5b761d289843b83009b008b3eb878cb94b439 (diff)
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.
-rw-r--r--pkg/cover/backend/dwarf.go50
1 files 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
})