cmd/go/internal/modindex: don't write index entry if file open

On Windows, we can't open a file that's already been opened. Before this
change, we'd try to write an index entry if mmapping the entry failed.
But that could happen either if the file doesn't exist or if there was a
problem mmapping an already opened file. Pass through information about
whether the file was actually opened so that we don't try to write to an
already opened file.

For #71059

Change-Id: I6adabe1093fed9ec37e7fafb13384c102786cbce
Reviewed-on: https://go-review.googlesource.com/c/go/+/640577
Reviewed-by: Sam Thanawalla <samthanawalla@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Michael Matloob 2025-01-06 11:10:02 -05:00
parent b2aa18b96c
commit b50ccef67a
3 changed files with 26 additions and 15 deletions

View file

@ -296,19 +296,19 @@ func GetBytes(c Cache, id ActionID) ([]byte, Entry, error) {
// GetMmap looks up the action ID in the cache and returns // GetMmap looks up the action ID in the cache and returns
// the corresponding output bytes. // the corresponding output bytes.
// GetMmap should only be used for data that can be expected to fit in memory. // GetMmap should only be used for data that can be expected to fit in memory.
func GetMmap(c Cache, id ActionID) ([]byte, Entry, error) { func GetMmap(c Cache, id ActionID) ([]byte, Entry, bool, error) {
entry, err := c.Get(id) entry, err := c.Get(id)
if err != nil { if err != nil {
return nil, entry, err return nil, entry, false, err
} }
md, err := mmap.Mmap(c.OutputFile(entry.OutputID)) md, opened, err := mmap.Mmap(c.OutputFile(entry.OutputID))
if err != nil { if err != nil {
return nil, Entry{}, err return nil, Entry{}, opened, err
} }
if int64(len(md.Data)) != entry.Size { if int64(len(md.Data)) != entry.Size {
return nil, Entry{}, &entryNotFoundError{Err: errors.New("file incomplete")} return nil, Entry{}, true, &entryNotFoundError{Err: errors.New("file incomplete")}
} }
return md.Data, entry, nil return md.Data, entry, true, nil
} }
// OutputFile returns the name of the cache file storing output with the given OutputID. // OutputFile returns the name of the cache file storing output with the given OutputID.

View file

@ -22,10 +22,11 @@ type Data struct {
} }
// Mmap maps the given file into memory. // Mmap maps the given file into memory.
func Mmap(file string) (Data, error) { func Mmap(file string) (Data, bool, error) {
f, err := os.Open(file) f, err := os.Open(file)
if err != nil { if err != nil {
return Data{}, err return Data{}, false, err
} }
return mmapFile(f) data, err := mmapFile(f)
return data, true, err
} }

View file

@ -183,18 +183,23 @@ func openIndexModule(modroot string, ismodcache bool) (*Module, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
data, _, err := cache.GetMmap(cache.Default(), id) data, _, opened, err := cache.GetMmap(cache.Default(), id)
if err != nil { if err != nil {
// Couldn't read from modindex. Assume we couldn't read from // Couldn't read from modindex. Assume we couldn't read from
// the index because the module hasn't been indexed yet. // the index because the module hasn't been indexed yet.
// But double check on Windows that we haven't opened the file yet,
// because once mmap opens the file, we can't close it, and
// Windows won't let us open an already opened file.
data, err = indexModule(modroot) data, err = indexModule(modroot)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if runtime.GOOS != "windows" || !opened {
if err = cache.PutBytes(cache.Default(), id, data); err != nil { if err = cache.PutBytes(cache.Default(), id, data); err != nil {
return nil, err return nil, err
} }
} }
}
mi, err := fromBytes(modroot, data) mi, err := fromBytes(modroot, data)
if err != nil { if err != nil {
return nil, err return nil, err
@ -212,15 +217,20 @@ func openIndexPackage(modroot, pkgdir string) (*IndexPackage, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
data, _, err := cache.GetMmap(cache.Default(), id) data, _, opened, err := cache.GetMmap(cache.Default(), id)
if err != nil { if err != nil {
// Couldn't read from index. Assume we couldn't read from // Couldn't read from index. Assume we couldn't read from
// the index because the package hasn't been indexed yet. // the index because the package hasn't been indexed yet.
// But double check on Windows that we haven't opened the file yet,
// because once mmap opens the file, we can't close it, and
// Windows won't let us open an already opened file.
data = indexPackage(modroot, pkgdir) data = indexPackage(modroot, pkgdir)
if runtime.GOOS != "windows" || !opened {
if err = cache.PutBytes(cache.Default(), id, data); err != nil { if err = cache.PutBytes(cache.Default(), id, data); err != nil {
return nil, err return nil, err
} }
} }
}
pkg, err := packageFromBytes(modroot, data) pkg, err := packageFromBytes(modroot, data)
if err != nil { if err != nil {
return nil, err return nil, err