]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go/internal/modindex: don't write index entry if file open
authorMichael Matloob <matloob@golang.org>
Mon, 6 Jan 2025 16:10:02 +0000 (11:10 -0500)
committerMichael Matloob <matloob@golang.org>
Tue, 7 Jan 2025 20:50:01 +0000 (12:50 -0800)
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>

src/cmd/go/internal/cache/cache.go
src/cmd/go/internal/mmap/mmap.go
src/cmd/go/internal/modindex/read.go

index c9acd8782db964b00d48f74d794e8392b0fb1b71..1bef1db08c7a8f24b8c552aec9446bf43db977e6 100644 (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
 // 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.
index fcbd3e08c1c5174f68bac1c6d5bd0fe0286e22cc..fd374df82efa1f2b41c9bb15a4ccb10628e6ecc1 100644 (file)
@@ -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
 }
index c4102409b433f312c7aa68f735c4ccb563c14d18..4c1fbd835961f65c0d4ac07fce3d4a8b2f63ee03 100644 (file)
@@ -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)
@@ -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)