cmd/go/internal/renameio: mask spurious "Access is denied" errors on Windows

Fixes #31247

Change-Id: I85a760a5d36ae835c97a13f980804d06b658857e
Reviewed-on: https://go-review.googlesource.com/c/go/+/172418
Run-TryBot: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Bryan C. Mills 2019-04-16 16:14:31 -04:00
parent 13b7c04d3f
commit 34b1f21046
1 changed files with 21 additions and 1 deletions

View File

@ -11,6 +11,9 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"runtime"
"strings"
"time"
) )
const patternSuffix = "*.tmp" const patternSuffix = "*.tmp"
@ -59,5 +62,22 @@ func WriteToFile(filename string, data io.Reader) (err error) {
if err := f.Close(); err != nil { if err := f.Close(); err != nil {
return err return err
} }
return os.Rename(f.Name(), filename)
var start time.Time
for {
err := os.Rename(f.Name(), filename)
if err == nil || runtime.GOOS != "windows" || !strings.HasSuffix(err.Error(), "Access is denied.") {
return err
}
// Windows seems to occasionally trigger spurious "Access is denied" errors
// here (see golang.org/issue/31247). We're not sure why. It's probably
// worth a little extra latency to avoid propagating the spurious errors.
if start.IsZero() {
start = time.Now()
} else if time.Since(start) >= 500*time.Millisecond {
return err
}
time.Sleep(5 * time.Millisecond)
}
} }