Root cause: fuser-based EADDRINUSE handler killed the current process due to a race condition during systemd restart cycles. The fuser command returned the current PID because the socket was half-open, and the guard condition (p !== process.pid) failed to filter it. Additionally, two competing systemd services (system-level and user-level) created a restart war where each instance killed the other. Fix approach (inspired by Next.js, Vite, webpack-dev-server): - Replace fuser with net.createServer port probe (no external commands) - PID-file based stale detection + ss fallback for orphan detection - Wait loop with 300ms polling after SIGTERM to stale process - Single-service architecture (disabled user-level unit) Tested: 5 consecutive rapid restarts, 8+ minute uptime, zero crashes. Co-Authored-By: zcode <noreply@zcode.dev>
580 B
580 B