Files
xarmian a0d6437ae6 test(testtmp): decide a template dir's owner by a held flock, not its pid (BUG-4088) (#2321)
testtmp.Sweep judged a template directory's owner dead with kill(pid,0)
on the pid in its name. A pid only means something inside one PID
namespace, and /tmp is shared across namespaces. A test binary run under
bwrap --unshare-pid got ESRCH for every host pid and deleted live
storetest templates mid-run ("copy template db: no such file"). In the
other direction, a pid recorded inside a sandbox can name an unrelated
host process and keep a dead owner's directory forever.

MkdirTemp now builds the directory under a staging name no sweep
matches, takes a flock on owner.lock, and renames it into place. The
lock follows the inode across the rename, and the fd is O_CLOEXEC and
held for the life of the process. Sweep removes a directory only when
it can take that lock. A directory with no owner.lock (made before this
change) keeps the old pid rule. Windows is unchanged.

Claude-Session: https://claude.ai/code/session_01Hk4vxsaKDm3E1LvsoHtHeV
2026-10-26 01:22:18 -04:00

26 lines
708 B
Go

//go:build windows
package testtmp
import (
"fmt"
"os"
)
// processAlive cannot ask cheaply here, so every owner counts as alive and
// a Windows sweep removes nothing.
func processAlive(int) bool { return true }
// ownedByMe is never consulted for removal here: processAlive keeps
// everything.
func ownedByMe(os.FileInfo) bool { return true }
// mkdirOwned takes no lock here: ownerState reports every directory as
// lockless, and processAlive then keeps it.
func mkdirOwned(dir, prefix string) (string, *os.File, error) {
path, err := os.MkdirTemp(dir, fmt.Sprintf("%s%d-*", prefix, os.Getpid()))
return path, nil, err
}
func ownerState(string) (ownership, func()) { return ownerNoLock, nil }