feat: Add Windows-compatible file locking for daemon
Replace Unix-only syscall.Flock with gofrs/flock library for cross-platform file locking. This enables the daemon to run on Windows in addition to Unix-like systems. - Add github.com/gofrs/flock v0.13.0 dependency - Replace syscall.Flock calls with flock.TryLock/Unlock - Maintain same non-blocking exclusive lock semantics (gt-5354h) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/gofrs/flock"
|
||||
"github.com/steveyegge/gastown/internal/beads"
|
||||
"github.com/steveyegge/gastown/internal/boot"
|
||||
"github.com/steveyegge/gastown/internal/config"
|
||||
@@ -70,18 +71,19 @@ func (d *Daemon) Run() error {
|
||||
// Acquire exclusive lock to prevent multiple daemons from running.
|
||||
// This prevents the TOCTOU race condition where multiple concurrent starts
|
||||
// can all pass the IsRunning() check before any writes the PID file.
|
||||
// Uses gofrs/flock for cross-platform compatibility (Unix + Windows).
|
||||
lockFile := filepath.Join(d.config.TownRoot, "daemon", "daemon.lock")
|
||||
lock, err := os.OpenFile(lockFile, os.O_CREATE|os.O_RDWR, 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("opening lock file: %w", err)
|
||||
}
|
||||
defer lock.Close()
|
||||
fileLock := flock.New(lockFile)
|
||||
|
||||
// Try to acquire exclusive lock (non-blocking)
|
||||
if err := syscall.Flock(int(lock.Fd()), syscall.LOCK_EX|syscall.LOCK_NB); err != nil {
|
||||
locked, err := fileLock.TryLock()
|
||||
if err != nil {
|
||||
return fmt.Errorf("acquiring lock: %w", err)
|
||||
}
|
||||
if !locked {
|
||||
return fmt.Errorf("daemon already running (lock held by another process)")
|
||||
}
|
||||
defer func() { _ = syscall.Flock(int(lock.Fd()), syscall.LOCK_UN) }()
|
||||
defer fileLock.Unlock()
|
||||
|
||||
// Write PID file
|
||||
if err := os.WriteFile(d.config.PidFile, []byte(strconv.Itoa(os.Getpid())), 0644); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user