Files
crush/internal/cmd/spawnlock_other.go
Christian RochaandCharm Crush d41c118511 fix(server): serialize concurrent server spawns with a per-host lock
When two clients started up at the same time they would both try to
spawn a server and one would lose the bind race, leaving a confusing
log behind. Take an exclusive file lock around the spawn-and-wait
sequence, re-check health after acquiring the lock, and skip the spawn
entirely if a peer client has already brought the server up. The lock
is released as soon as the new server is ready.

Co-Authored-By: Charm Crush <crush@charm.land>
2026-05-11 20:24:07 -04:00

29 lines
707 B
Go

//go:build !windows
package cmd
import (
"fmt"
"os"
"golang.org/x/sys/unix"
)
// acquireSpawnLock takes an exclusive flock on the given file (creating
// it if necessary) and returns a release function that unlocks and
// closes the file. Blocks until the lock is acquired.
func acquireSpawnLock(path string) (func(), error) {
f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0o600)
if err != nil {
return nil, fmt.Errorf("open spawn lock %q: %v", path, err)
}
if err := unix.Flock(int(f.Fd()), unix.LOCK_EX); err != nil {
_ = f.Close()
return nil, fmt.Errorf("flock spawn lock %q: %v", path, err)
}
return func() {
_ = unix.Flock(int(f.Fd()), unix.LOCK_UN)
_ = f.Close()
}, nil
}