1
0
mirror of https://github.com/golang/go synced 2024-11-18 18:04:46 -07:00

internal/lsp/cache: fix mod file change check

The modfiles function only works with Go 1.14. When it is enabled,
it reenters the view, causing a deadlock. Stop using it, and move the
process env under a separate lock so to break the deadlock.

Change-Id: I34c528c2be1f32c06b423ead44e90155f60c2214
Reviewed-on: https://go-review.googlesource.com/c/tools/+/215679
Run-TryBot: Heschi Kreinick <heschi@google.com>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Heschi Kreinick 2020-01-21 13:57:40 -05:00
parent 13c74800b9
commit 9375b12bd8

View File

@ -60,6 +60,8 @@ type view struct {
// mod is the module information for this view.
mod *moduleInformation
// importsMu guards imports-related state, particularly the ProcessEnv.
importsMu sync.Mutex
// process is the process env for this view.
// Note: this contains cached module and filesystem state.
//
@ -274,8 +276,9 @@ func (v *view) Config(ctx context.Context) *packages.Config {
}
func (v *view) RunProcessEnvFunc(ctx context.Context, fn func(*imports.Options) error) error {
v.mu.Lock()
defer v.mu.Unlock()
v.importsMu.Lock()
defer v.importsMu.Unlock()
if v.processEnv == nil {
var err error
if v.processEnv, err = v.buildProcessEnv(ctx); err != nil {
@ -284,11 +287,12 @@ func (v *view) RunProcessEnvFunc(ctx context.Context, fn func(*imports.Options)
}
// In module mode, check if the mod file has changed.
if mod, _, err := v.Snapshot().ModFiles(ctx); err == nil && mod != nil {
if mod.Identity() != v.cachedModFileVersion {
if v.gomod != "" && v.gomod != os.DevNull {
mod, err := v.Snapshot().GetFile(span.FileURI(v.gomod))
if err == nil && mod.Identity() != v.cachedModFileVersion {
v.processEnv.GetResolver().(*imports.ModuleResolver).ClearForNewMod()
v.cachedModFileVersion = mod.Identity()
}
v.cachedModFileVersion = mod.Identity()
}
// Run the user function.
@ -323,20 +327,20 @@ func (v *view) RunProcessEnvFunc(ctx context.Context, fn func(*imports.Options)
func (v *view) refreshProcessEnv() {
start := time.Now()
v.mu.Lock()
v.importsMu.Lock()
env := v.processEnv
env.GetResolver().ClearForNewScan()
v.mu.Unlock()
v.importsMu.Unlock()
// We don't have a context handy to use for logging, so use the stdlib for now.
stdlog.Printf("background imports cache refresh starting")
err := imports.PrimeCache(context.Background(), env)
stdlog.Printf("background refresh finished after %v with err: %v", time.Since(start), err)
v.mu.Lock()
v.importsMu.Lock()
v.cacheRefreshDuration = time.Since(start)
v.cacheRefreshTimer = nil
v.mu.Unlock()
v.importsMu.Unlock()
}
func (v *view) buildProcessEnv(ctx context.Context) (*imports.ProcessEnv, error) {