carlos / platform Public

stopevidence test: wait until fd 3 holds the database by identity before scanning (flaky on arm64 CI)

The namespace holder's fd 3 can be the dynamic loader's libc while unshare
or sh starts, so the old wait (any readlink text) scanned too early.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev fb55e96d2f36ae53901393b63a1c92c97aa2eef1 parent 412ca78
1 file changed, +14 −3
  • internal/stopevidence/fdholders_alias_linux_test.go +14 −3

CI passed — run details

diff --git a/internal/stopevidence/fdholders_alias_linux_test.go b/internal/stopevidence/fdholders_alias_linux_test.go
index 6c9971286..b0ee488ce 100644
--- a/internal/stopevidence/fdholders_alias_linux_test.go
+++ b/internal/stopevidence/fdholders_alias_linux_test.go
@@ -132,14 +132,25 @@ func TestFDIdentityFindsAHolderInAnotherMountNamespace(t *testing.T) {
t.Cleanup(func() { cmd.Process.Kill(); cmd.Wait() })
pid := cmd.Process.Pid
fd3 := filepath.Join("/proc", strconv.Itoa(pid), "fd", "3")
+ // Until sh has run the mount and exec'd sleep, fd 3 can be some other
+ // file (the dynamic loader's libc, while unshare or sh starts), so wait
+ // for fd 3 to be the database itself, by identity: stat through the
+ // magic link reaches the file the descriptor holds in any namespace.
+ want, err := os.Stat(db)
+ if err != nil {
+ t.Fatal(err)
+ }
var target string
+ held := false
for deadline := time.Now().Add(5 * time.Second); time.Now().Before(deadline); time.Sleep(20 * time.Millisecond) {
- if target, _ = os.Readlink(fd3); target != "" {
+ if fi, err := os.Stat(fd3); err == nil && os.SameFile(fi, want) {
+ target, _ = os.Readlink(fd3)
+ held = true
break
}
}
- if target == "" {
- t.Skip("the namespace holder never came up (unprivileged user namespaces refused?)")
+ if !held {
+ t.Skip("the namespace holder never came up holding the database (unprivileged user namespaces refused?)")
}
if target != aliased {
t.Logf("descriptor text %q (expected the bind path %q)", target, aliased)