]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go/internal/modfetch: fix concurrent read/write race in modfetch
authorRuss Cox <rsc@golang.org>
Tue, 30 Apr 2019 01:29:16 +0000 (21:29 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 30 Apr 2019 13:12:48 +0000 (13:12 +0000)
On Windows systems, the failure rate for cmd/go's TestScript/mod_concurrent
is somewhere around 3-10% without this change. With the change, I have yet
to see a failure.

Fixes #31744.

Change-Id: Ib321ebb9556dd8438086cf329dfa083a9e051732
Reviewed-on: https://go-review.googlesource.com/c/go/+/174439
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/go/internal/modfetch/sumdb.go

index b01aad8333efcad56efb31958e3891b09058bf87..ebfb95b7160fe2ed83f1011ac022525fa7f80b74 100644 (file)
@@ -233,7 +233,15 @@ func (*dbClient) WriteConfig(file string, old, new []byte) error {
 // which will be deleted by "go clean -modcache".
 func (*dbClient) ReadCache(file string) ([]byte, error) {
        targ := filepath.Join(PkgMod, "download/cache/sumdb", file)
-       return lockedfile.Read(targ)
+       data, err := lockedfile.Read(targ)
+       // lockedfile.Write does not atomically create the file with contents.
+       // There is a moment between file creation and locking the file for writing,
+       // during which the empty file can be locked for reading.
+       // Treat observing an empty file as file not found.
+       if err == nil && len(data) == 0 {
+               err = &os.PathError{Op: "read", Path: targ, Err: os.ErrNotExist}
+       }
+       return data, err
 }
 
 // WriteCache updates cached lookups or tiles.