From: Russ Cox Date: Tue, 30 Apr 2019 01:29:16 +0000 (-0400) Subject: cmd/go/internal/modfetch: fix concurrent read/write race in modfetch X-Git-Tag: go1.13beta1~491 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=8e28cd19acc43437e7ccec25dd0572afd6b77f8a;p=gostls13.git cmd/go/internal/modfetch: fix concurrent read/write race in modfetch 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 Reviewed-by: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- diff --git a/src/cmd/go/internal/modfetch/sumdb.go b/src/cmd/go/internal/modfetch/sumdb.go index b01aad8333..ebfb95b716 100644 --- a/src/cmd/go/internal/modfetch/sumdb.go +++ b/src/cmd/go/internal/modfetch/sumdb.go @@ -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.