ref/v23tests: improve concurrent access to V23_BIN_DIR
Prior to this CL, multiple processes sharing a V23_BIN_DIR would
concurrently build and copy over the same binaries. This CL
ensures that every build uses a different output name and then
uses the atomic Rename operation to move the new binary to its
final name. Whilst working on this it seems that concurrent Renames
will not be serialized, rather all-but-one, will fail, hence if the
backoff code that retries the rename after a random period.
Change-Id: Ie248c3134574b36ca8241d12076b9073d4926057
diff --git a/test/v23tests/v23tests.go b/test/v23tests/v23tests.go
index 9f78de7..3496356 100644
--- a/test/v23tests/v23tests.go
+++ b/test/v23tests/v23tests.go
@@ -8,6 +8,7 @@
"errors"
"fmt"
"io/ioutil"
+ "math/rand"
"os"
"os/exec"
"path"
@@ -18,9 +19,11 @@
"testing"
"time"
+ "v.io/x/lib/vlog"
+
"v.io/v23"
"v.io/v23/security"
- "v.io/x/lib/vlog"
+
"v.io/x/ref/envvar"
"v.io/x/ref/services/agent"
"v.io/x/ref/test"
@@ -554,15 +557,33 @@
// function.
func buildPkg(binDir, pkg string) (bool, string, error) {
binFile := filepath.Join(binDir, path.Base(pkg))
+ vlog.Infof("buildPkg: %v .. %v", binDir, pkg)
if _, err := os.Stat(binFile); err != nil {
if !os.IsNotExist(err) {
return false, "", err
}
- cmd := exec.Command("v23", "go", "build", "-o", binFile, pkg)
+ baseName := path.Base(binFile)
+ tmpdir, err := ioutil.TempDir(binDir, baseName+"-")
+ if err != nil {
+ return false, "", err
+ }
+ defer os.RemoveAll(tmpdir)
+ uniqueBinFile := filepath.Join(tmpdir, baseName)
+
+ cmd := exec.Command("v23", "go", "build", "-x", "-o", uniqueBinFile, pkg)
if output, err := cmd.CombinedOutput(); err != nil {
vlog.VI(1).Infof("\n%v:\n%v\n", strings.Join(cmd.Args, " "), string(output))
return false, "", err
}
+ if err := os.Rename(uniqueBinFile, binFile); err != nil {
+ // It seems that on some systems a rename may fail if another rename
+ // is in progress in the same directory. We back a random amount of time
+ // in the hope that a second attempt will succeed.
+ time.Sleep(time.Duration(rand.Int63n(1000)) * time.Millisecond)
+ if err := os.Rename(uniqueBinFile, binFile); err != nil {
+ return false, "", err
+ }
+ }
return false, binFile, nil
}
return true, binFile, nil