test: write-then-rename script-bin helpers (avoid ETXTBSY under -race)
CI run #48 failed with: --- FAIL: TestRunInitShipsStartedAndFinished RunInit: ... fork/exec /tmp/.../restic: text file busy setupScript and setupScriptBin used os.WriteFile to write a shell script directly at the final path, then exec'd it. Under -race + many t.Parallel tests, a fork-from-another-goroutine could inherit the still-open writable fd from one of those WriteFile calls; the kernel returns ETXTBSY when the freshly-execed binary still has a writable fd anywhere on the system. Fix: write to "<path>.tmp", then os.Rename into place. The rename is a pure dirent op; by the time the final path exists, no process has a writable fd on its inode and exec is safe. -race + -count=5 on both runner packages now passes consistently.
This commit is contained in:
@@ -13,15 +13,23 @@ import (
|
||||
// makes it executable, and returns its path. scriptBody is the
|
||||
// complete script content (without the shebang line — that's added
|
||||
// automatically).
|
||||
// Writes to "<path>.tmp" then renames into place — see the matching
|
||||
// helper in internal/agent/runner/runner_test.go for the ETXTBSY
|
||||
// race rationale. Same fix applied here so this helper doesn't lose
|
||||
// the race the next time CI gets unlucky.
|
||||
func setupScriptBin(t *testing.T, scriptBody string) string {
|
||||
t.Helper()
|
||||
dir := t.TempDir()
|
||||
p := filepath.Join(dir, "restic")
|
||||
final := filepath.Join(dir, "restic")
|
||||
tmp := final + ".tmp"
|
||||
content := "#!/bin/sh\n" + scriptBody + "\n"
|
||||
if err := os.WriteFile(p, []byte(content), 0o755); err != nil {
|
||||
t.Fatalf("setupScriptBin: %v", err)
|
||||
if err := os.WriteFile(tmp, []byte(content), 0o755); err != nil {
|
||||
t.Fatalf("setupScriptBin: write tmp: %v", err)
|
||||
}
|
||||
return p
|
||||
if err := os.Rename(tmp, final); err != nil {
|
||||
t.Fatalf("setupScriptBin: rename: %v", err)
|
||||
}
|
||||
return final
|
||||
}
|
||||
|
||||
// captureLines returns a LineHandler that appends "stream:line" into
|
||||
|
||||
Reference in New Issue
Block a user