diff options
author | Nia Waldvogel <[email protected]> | 2021-12-15 09:39:55 -0500 |
---|---|---|
committer | Ayke <[email protected]> | 2021-12-17 09:33:28 +0100 |
commit | d5c0083085f7104b3f0d41290bb2ab4ccc2e5cac (patch) | |
tree | f08b5c952e34c827782236a18191abac6b425bde /builder/library.go | |
parent | e6fbad13c6caee9ef233ae16a6c95518195f8f70 (diff) | |
download | tinygo-d5c0083085f7104b3f0d41290bb2ab4ccc2e5cac.tar.gz tinygo-d5c0083085f7104b3f0d41290bb2ab4ccc2e5cac.zip |
builder: handle concurrent library header rename
When a library is built concurrently by multiple TinyGo processes, they may sometimes both build the headers.
In that case a directory rename may fail due to conflict.
This change detects and handles the conflict similar to how GOROOT construction does.
Diffstat (limited to 'builder/library.go')
-rw-r--r-- | builder/library.go | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/builder/library.go b/builder/library.go index 730797854..efcc8b75a 100644 --- a/builder/library.go +++ b/builder/library.go @@ -4,6 +4,7 @@ import ( "io/ioutil" "os" "path/filepath" + "runtime" "strings" "github.com/tinygo-org/tinygo/compileopts" @@ -92,7 +93,23 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ } err = os.Rename(temporaryHeaderPath, headerPath) if err != nil { - return nil, err + switch { + case os.IsExist(err): + // Another invocation of TinyGo also seems to have already created the headers. + + case runtime.GOOS == "windows" && os.IsPermission(err): + // On Windows, a rename with a destination directory that already + // exists does not result in an IsExist error, but rather in an + // access denied error. To be sure, check for this case by checking + // whether the target directory exists. + if _, err := os.Stat(headerPath); err == nil { + break + } + fallthrough + + default: + return nil, err + } } } } |