From e97d93503ddae7243aa3a275f18df4a62a3c9daa Mon Sep 17 00:00:00 2001 From: zhernrong92 <46508817+zhernrong92@users.noreply.github.com> Date: Fri, 19 Jun 2026 23:20:55 +0800 Subject: [PATCH] fix: make local-dev (make dev) work on non-root / NFS hosts (#3590) * fix(scripts): avoid lsof hang during make dev cleanup on NFS `_is_deerflow_pid` and `_report_reclaimed_ports` call `lsof -p ` to enumerate a process's open files. On hosts whose working tree or home is on a network filesystem (NFS/autofs), `lsof -p` blocks indefinitely on the kernel stat calls, so `make dev` / `make stop` hang forever at "Stopping all services...". Add `-b` (avoid kernel blocking functions) and `-w` (suppress the resulting warnings) to both calls. The network-only `lsof -nP -iTCP` probes are unaffected and already returned quickly. Co-Authored-By: Claude Opus 4.8 (1M context) * fix(nginx): set global error_log so local-dev nginx starts as non-root nginx.local.conf only declared `error_log` inside the `http {}` block. nginx opens its compiled-in default error log (on Debian/Ubuntu builds, the absolute /var/log/nginx/error.log) at startup, before it reaches the http-block directive. When `make dev` launches nginx as a non-root user that path is not writable, so startup fails with: [emerg] open() "/var/log/nginx/error.log" failed (13: Permission denied) Declare a global (main-context) `error_log logs/nginx-error.log warn;`. Combined with the existing `-p $REPO_ROOT`, logging resolves to the repo-local logs/ directory and nginx starts without elevated privileges. Co-Authored-By: Claude Opus 4.8 (1M context) --------- Co-authored-by: Claude Opus 4.8 (1M context) --- docker/nginx/nginx.local.conf | 4 ++++ scripts/serve.sh | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docker/nginx/nginx.local.conf b/docker/nginx/nginx.local.conf index 035406862..16c7de0b1 100644 --- a/docker/nginx/nginx.local.conf +++ b/docker/nginx/nginx.local.conf @@ -1,3 +1,7 @@ +# Global error_log (main context). Without this, nginx opens its compiled-in +# default (/var/log/nginx/error.log) at startup before reaching the http-block +# error_log, which fails with permission denied when run as a non-root user. +error_log logs/nginx-error.log warn; events { worker_connections 1024; } diff --git a/scripts/serve.sh b/scripts/serve.sh index aac16f1fc..bc8d58938 100755 --- a/scripts/serve.sh +++ b/scripts/serve.sh @@ -105,7 +105,7 @@ _is_deerflow_pid() { return 0 fi - files=$(lsof -p "$pid" 2>/dev/null) || return 1 + files=$(lsof -b -w -p "$pid" 2>/dev/null) || return 1 while IFS= read -r root; do [ -n "$root" ] || continue case "$files" in @@ -122,7 +122,7 @@ _report_reclaimed_ports() { for port in 8001 3000 2026; do for pid in $(lsof -nP -iTCP:"$port" -sTCP:LISTEN -t 2>/dev/null); do _is_deerflow_pid "$pid" || continue - files=$(lsof -p "$pid" 2>/dev/null) + files=$(lsof -b -w -p "$pid" 2>/dev/null) case "$files" in *"$REPO_ROOT"/*) continue ;; esac # this worktree — normal owner="" while IFS= read -r root; do