From 2194d447e9e0bf59e1ccea0870b920a4e7df1710 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Wed, 26 Aug 2020 09:26:51 +0200 Subject: [PATCH] loader: use ioutil.TempDir to create a temporary directory ... instead of generating one with math/rand. The problem was that math/rand is deterministic across runs, resulting in a possible race when trying to create the same directory between two processes. Additionally, because I used `os.MkdirAll`, no error was reported when the directory already existed. The solution to this is to use the stdlib function designed for this: ioutil.TempDir. --- loader/goroot.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/loader/goroot.go b/loader/goroot.go index 621b92cb..d1c5d1c3 100644 --- a/loader/goroot.go +++ b/loader/goroot.go @@ -10,13 +10,11 @@ import ( "fmt" "io" "io/ioutil" - "math/rand" "os" "os/exec" "path" "path/filepath" "runtime" - "strconv" "github.com/tinygo-org/tinygo/compileopts" "github.com/tinygo-org/tinygo/goenv" @@ -50,7 +48,8 @@ func GetCachedGoroot(config *compileopts.Config) (string, error) { fmt.Fprintln(hash, tinygoroot) gorootsHash := hash.Sum(nil) gorootsHashHex := hex.EncodeToString(gorootsHash[:]) - cachedgoroot := filepath.Join(goenv.Get("GOCACHE"), "goroot-"+version+"-"+gorootsHashHex) + cachedgorootName := "goroot-" + version + "-" + gorootsHashHex + cachedgoroot := filepath.Join(goenv.Get("GOCACHE"), cachedgorootName) if needsSyscallPackage(config.BuildTags()) { cachedgoroot += "-syscall" } @@ -58,8 +57,11 @@ func GetCachedGoroot(config *compileopts.Config) (string, error) { if _, err := os.Stat(cachedgoroot); err == nil { return cachedgoroot, nil } - tmpgoroot := cachedgoroot + ".tmp" + strconv.Itoa(rand.Int()) - err = os.MkdirAll(tmpgoroot, 0777) + err = os.MkdirAll(goenv.Get("GOCACHE"), 0777) + if err != nil { + return "", err + } + tmpgoroot, err := ioutil.TempDir(goenv.Get("GOCACHE"), cachedgorootName+".tmp") if err != nil { return "", err }