Skip to content

Commit

Permalink
Protect NewFilenameUnadjuster from concurrent map writes (#1192)
Browse files Browse the repository at this point in the history
  • Loading branch information
Helcaraxan authored Jun 25, 2020
1 parent 38d298c commit 5f0de29
Showing 1 changed file with 15 additions and 7 deletions.
22 changes: 15 additions & 7 deletions pkg/result/processors/filename_unadjuster.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ import (

type posMapper func(pos token.Position) token.Position

type adjustMap struct {
sync.Mutex
m map[string]posMapper
}

// FilenameUnadjuster is needed because a lot of linters use fset.Position(f.Pos())
// to get filename. And they return adjusted filename (e.g. *.qtpl) for an issue. We need
// restore real .go filename to properly output it, parse it, etc.
Expand All @@ -27,7 +32,7 @@ type FilenameUnadjuster struct {

var _ Processor = &FilenameUnadjuster{}

func processUnadjusterPkg(m map[string]posMapper, pkg *packages.Package, log logutils.Log) {
func processUnadjusterPkg(m *adjustMap, pkg *packages.Package, log logutils.Log) {
fset := token.NewFileSet() // it's more memory efficient to not store all in one fset

for _, filename := range pkg.CompiledGoFiles {
Expand All @@ -36,7 +41,7 @@ func processUnadjusterPkg(m map[string]posMapper, pkg *packages.Package, log log
}
}

func processUnadjusterFile(filename string, m map[string]posMapper, log logutils.Log, fset *token.FileSet) {
func processUnadjusterFile(filename string, m *adjustMap, log logutils.Log, fset *token.FileSet) {
syntax, err := parser.ParseFile(fset, filename, nil, parser.ParseComments)
if err != nil {
// Error will be reported by typecheck
Expand All @@ -57,7 +62,9 @@ func processUnadjusterFile(filename string, m map[string]posMapper, log logutils
return // file.go -> /caches/cgo-xxx
}

m[adjustedFilename] = func(adjustedPos token.Position) token.Position {
m.Lock()
defer m.Unlock()
m.m[adjustedFilename] = func(adjustedPos token.Position) token.Position {
tokenFile := fset.File(syntax.Pos())
if tokenFile == nil {
log.Warnf("Failed to get token file for %s", adjustedFilename)
Expand All @@ -68,22 +75,23 @@ func processUnadjusterFile(filename string, m map[string]posMapper, log logutils
}

func NewFilenameUnadjuster(pkgs []*packages.Package, log logutils.Log) *FilenameUnadjuster {
m := map[string]posMapper{}
m := adjustMap{m: map[string]posMapper{}}

startedAt := time.Now()
var wg sync.WaitGroup
wg.Add(len(pkgs))
for _, pkg := range pkgs {
go func(pkg *packages.Package) {
// It's important to call func here to run GC
processUnadjusterPkg(m, pkg, log)
processUnadjusterPkg(&m, pkg, log)
wg.Done()
}(pkg)
}
wg.Wait()
log.Infof("Pre-built %d adjustments in %s", len(m), time.Since(startedAt))
log.Infof("Pre-built %d adjustments in %s", len(m.m), time.Since(startedAt))

return &FilenameUnadjuster{
m: m,
m: m.m,
log: log,
loggedUnadjustments: map[string]bool{},
}
Expand Down

0 comments on commit 5f0de29

Please sign in to comment.