fix(run.sh): correct PID capture with process substitution, add SIGTERM trap, 3-phase cleanup
Problem: pipeline cmd | awk & captured awks PID instead of Python PID. When cleanup killed AGENT_PID, awk died but Gradio kept port 7860 occupied. Fix: - Replace | awk & with > >(awk) 2>&1 & (process substitution) so 0 gives real PID - Trap SIGTERM + SIGHUP in addition to SIGINT - Three-phase cleanup: SIGTERM -> wait 1s -> SIGKILL -> fuser port fallback
This commit is contained in:
48
run.sh
48
run.sh
@@ -186,21 +186,43 @@ setup_frontend
|
||||
cleanup() {
|
||||
echo ""
|
||||
echo "Stopping services..."
|
||||
|
||||
# Phase 1: kill by tracked PID (process substitution ensures correct PID capture)
|
||||
if [ -n "$BACKEND_PID" ]; then
|
||||
kill $BACKEND_PID 2>/dev/null || true
|
||||
kill -TERM $BACKEND_PID 2>/dev/null || true
|
||||
fi
|
||||
if [ -n "$FRONTEND_PID" ]; then
|
||||
kill $FRONTEND_PID 2>/dev/null || true
|
||||
kill -TERM $FRONTEND_PID 2>/dev/null || true
|
||||
fi
|
||||
if [ -n "$AGENT_PID" ]; then
|
||||
kill $AGENT_PID 2>/dev/null || true
|
||||
kill -TERM $AGENT_PID 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Phase 2: wait for graceful exit (up to 2s), then force kill
|
||||
sleep 1
|
||||
if [ -n "$BACKEND_PID" ]; then
|
||||
kill -KILL $BACKEND_PID 2>/dev/null || true
|
||||
fi
|
||||
if [ -n "$FRONTEND_PID" ]; then
|
||||
kill -KILL $FRONTEND_PID 2>/dev/null || true
|
||||
fi
|
||||
if [ -n "$AGENT_PID" ]; then
|
||||
kill -KILL $AGENT_PID 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Phase 3: fuser fallback — kill anything still on our ports (belt-and-suspenders)
|
||||
if command -v fuser &>/dev/null; then
|
||||
fuser -k ${AGENT_PORT}/tcp 2>/dev/null || true
|
||||
fuser -k ${BACKEND_PORT}/tcp 2>/dev/null || true
|
||||
fuser -k ${FRONTEND_PORT}/tcp 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo "Services stopped."
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Trap SIGINT (Ctrl+C)
|
||||
trap cleanup SIGINT
|
||||
# Trap SIGINT (Ctrl+C), SIGTERM (kill), and SIGHUP (terminal close)
|
||||
trap cleanup SIGINT SIGTERM SIGHUP
|
||||
|
||||
# Start Backend
|
||||
start_backend() {
|
||||
@@ -234,8 +256,8 @@ start_backend() {
|
||||
fi
|
||||
local _color=$'\033[0;34m[Backend]\033[0m '
|
||||
PYTHONUNBUFFERED=1 python3 -m uvicorn src.app:app --port "$BACKEND_PORT" \
|
||||
"${uvicorn_env_args[@]}" "${reload_args[@]}" 2>&1 | \
|
||||
awk -v prefix="$_color " '{print prefix $0; fflush()}' &
|
||||
"${uvicorn_env_args[@]}" "${reload_args[@]}" \
|
||||
> >(awk -v prefix="$_color " '{print prefix $0; fflush()}') 2>&1 &
|
||||
BACKEND_PID=$!
|
||||
cd ..
|
||||
}
|
||||
@@ -247,8 +269,8 @@ start_frontend() {
|
||||
local _color=$'\033[0;32m[Frontend]\033[0m '
|
||||
BACKEND_URL="http://127.0.0.1:${BACKEND_PORT}" \
|
||||
GRADIO_URL="http://127.0.0.1:${AGENT_PORT}" \
|
||||
npm run dev -- --port "$FRONTEND_PORT" 2>&1 | \
|
||||
awk -v prefix="$_color " '{print prefix $0; fflush()}' &
|
||||
npm run dev -- --port "$FRONTEND_PORT" \
|
||||
> >(awk -v prefix="$_color " '{print prefix $0; fflush()}') 2>&1 &
|
||||
FRONTEND_PID=$!
|
||||
cd ..
|
||||
}
|
||||
@@ -276,11 +298,11 @@ start_agent() {
|
||||
if [ "$DEV_MODE" = "true" ]; then
|
||||
echo -e "\033[0;35m[Agent]\033[0m Hot-reload enabled via watchfiles (watching src/agent/)"
|
||||
PYTHONUNBUFFERED=1 python3 -m watchfiles --filter python \
|
||||
"python -m src.agent.run" src/agent 2>&1 | \
|
||||
awk -v prefix="$_color " '{print prefix $0; fflush()}' &
|
||||
"python -m src.agent.run" src/agent \
|
||||
> >(awk -v prefix="$_color " '{print prefix $0; fflush()}') 2>&1 &
|
||||
else
|
||||
PYTHONUNBUFFERED=1 python3 -m src.agent.run 2>&1 | \
|
||||
awk -v prefix="$_color " '{print prefix $0; fflush()}' &
|
||||
PYTHONUNBUFFERED=1 python3 -m src.agent.run \
|
||||
> >(awk -v prefix="$_color " '{print prefix $0; fflush()}') 2>&1 &
|
||||
fi
|
||||
AGENT_PID=$!
|
||||
cd ..
|
||||
|
||||
Reference in New Issue
Block a user