Skip to content

Commit

Permalink
cmd/go/internal/modindex: don't write index entry if file open
Browse files Browse the repository at this point in the history
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 golang#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>
  • Loading branch information
matloob authored and wyf9661 committed Jan 21, 2025
1 parent 34ae364 commit 32ce9f6
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 15 deletions.
12 changes: 6 additions & 6 deletions src/cmd/go/internal/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,19 +296,19 @@ func GetBytes(c Cache, id ActionID) ([]byte, Entry, error) {
// GetMmap looks up the action ID in the cache and returns
// the corresponding output bytes.
// 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)
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 {
return nil, Entry{}, err
return nil, Entry{}, opened, err
}
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.
Expand Down
7 changes: 4 additions & 3 deletions src/cmd/go/internal/mmap/mmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ type Data struct {
}

// 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)
if err != nil {
return Data{}, err
return Data{}, false, err
}
return mmapFile(f)
data, err := mmapFile(f)
return data, true, err
}
22 changes: 16 additions & 6 deletions src/cmd/go/internal/modindex/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,16 +183,21 @@ func openIndexModule(modroot string, ismodcache bool) (*Module, error) {
if err != nil {
return nil, err
}
data, _, err := cache.GetMmap(cache.Default(), id)
data, _, opened, err := cache.GetMmap(cache.Default(), id)
if err != nil {
// Couldn't read from modindex. Assume we couldn't read from
// 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)
if err != nil {
return nil, err
}
if err = cache.PutBytes(cache.Default(), id, data); err != nil {
return nil, err
if runtime.GOOS != "windows" || !opened {
if err = cache.PutBytes(cache.Default(), id, data); err != nil {
return nil, err
}
}
}
mi, err := fromBytes(modroot, data)
Expand All @@ -212,13 +217,18 @@ func openIndexPackage(modroot, pkgdir string) (*IndexPackage, error) {
if err != nil {
return nil, err
}
data, _, err := cache.GetMmap(cache.Default(), id)
data, _, opened, err := cache.GetMmap(cache.Default(), id)
if err != nil {
// Couldn't read from index. Assume we couldn't read from
// 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)
if err = cache.PutBytes(cache.Default(), id, data); err != nil {
return nil, err
if runtime.GOOS != "windows" || !opened {
if err = cache.PutBytes(cache.Default(), id, data); err != nil {
return nil, err
}
}
}
pkg, err := packageFromBytes(modroot, data)
Expand Down

0 comments on commit 32ce9f6

Please sign in to comment.