bd-vcg5: Add daemon crash recovery with panic handler + socket cleanup

Improvements:
1. Added top-level panic recovery in runDaemonLoop
   - Captures stack trace and logs to daemon.log
   - Writes daemon-error file with crash details for user visibility
   - Cleans up PID file on panic
2. Replaced os.Exit calls with return statements where possible
   - Allows deferred cleanup to run (lock release, socket removal, etc)
   - Improves graceful shutdown on errors
3. Enhanced stopDaemon forced-kill path
   - Removes stale socket file after process.Kill()
   - Prevents socket artifacts from accumulating
4. Added integration tests for crash recovery

Closes bd-vcg5
This commit is contained in:
Steve Yegge
2025-11-07 21:17:24 -08:00
parent f6bdf7c641
commit 00f045a972
3 changed files with 235 additions and 10 deletions

View File

@@ -334,13 +334,28 @@ func stopDaemon(pidFile string) {
fmt.Println("Daemon stopped")
return
}
// Determine if this is global or local daemon
isGlobal := strings.Contains(pidFile, filepath.Join(".beads", "daemon.lock"))
socketPath := getSocketPathForPID(pidFile, isGlobal)
if err := process.Kill(); err != nil {
// Ignore "process already finished" errors
if !strings.Contains(err.Error(), "process already finished") {
fmt.Fprintf(os.Stderr, "Error killing process: %v\n", err)
}
}
// Clean up stale artifacts after forced kill
_ = os.Remove(pidFile)
// Also remove socket file if it exists
if _, err := os.Stat(socketPath); err == nil {
if err := os.Remove(socketPath); err != nil {
fmt.Fprintf(os.Stderr, "Warning: failed to remove stale socket: %v\n", err)
}
}
fmt.Println("Daemon killed")
}