Protect NewFilenameUnadjuster from concurrent map writes (#1192)
This commit is contained in:
parent
38d298c2c8
commit
5f0de2982b
@ -16,6 +16,11 @@ import (
|
|||||||
|
|
||||||
type posMapper func(pos token.Position) token.Position
|
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())
|
// 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
|
// 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.
|
// restore real .go filename to properly output it, parse it, etc.
|
||||||
@ -27,7 +32,7 @@ type FilenameUnadjuster struct {
|
|||||||
|
|
||||||
var _ Processor = &FilenameUnadjuster{}
|
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
|
fset := token.NewFileSet() // it's more memory efficient to not store all in one fset
|
||||||
|
|
||||||
for _, filename := range pkg.CompiledGoFiles {
|
for _, filename := range pkg.CompiledGoFiles {
|
||||||
@ -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)
|
syntax, err := parser.ParseFile(fset, filename, nil, parser.ParseComments)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Error will be reported by typecheck
|
// Error will be reported by typecheck
|
||||||
@ -57,7 +62,9 @@ func processUnadjusterFile(filename string, m map[string]posMapper, log logutils
|
|||||||
return // file.go -> /caches/cgo-xxx
|
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())
|
tokenFile := fset.File(syntax.Pos())
|
||||||
if tokenFile == nil {
|
if tokenFile == nil {
|
||||||
log.Warnf("Failed to get token file for %s", adjustedFilename)
|
log.Warnf("Failed to get token file for %s", adjustedFilename)
|
||||||
@ -68,22 +75,23 @@ func processUnadjusterFile(filename string, m map[string]posMapper, log logutils
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewFilenameUnadjuster(pkgs []*packages.Package, log logutils.Log) *FilenameUnadjuster {
|
func NewFilenameUnadjuster(pkgs []*packages.Package, log logutils.Log) *FilenameUnadjuster {
|
||||||
m := map[string]posMapper{}
|
m := adjustMap{m: map[string]posMapper{}}
|
||||||
|
|
||||||
startedAt := time.Now()
|
startedAt := time.Now()
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(len(pkgs))
|
wg.Add(len(pkgs))
|
||||||
for _, pkg := range pkgs {
|
for _, pkg := range pkgs {
|
||||||
go func(pkg *packages.Package) {
|
go func(pkg *packages.Package) {
|
||||||
// It's important to call func here to run GC
|
// It's important to call func here to run GC
|
||||||
processUnadjusterPkg(m, pkg, log)
|
processUnadjusterPkg(&m, pkg, log)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}(pkg)
|
}(pkg)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
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{
|
return &FilenameUnadjuster{
|
||||||
m: m,
|
m: m.m,
|
||||||
log: log,
|
log: log,
|
||||||
loggedUnadjustments: map[string]bool{},
|
loggedUnadjustments: map[string]bool{},
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user