mirror of
https://github.com/Comfy-Org/ComfyUI-Manager.git
synced 2026-06-23 00:09:25 +08:00
Some checks are pending
Python Linting / Run Ruff (push) Waiting to run
* feat(security): add dedicated install flags decoupled from security_level Gate 'install via git URL' and 'install via pip' with dedicated opt-in boolean flags (allow_git_url_install / allow_pip_install) in config.ini [default], fully replacing the security_level term on those surfaces (REPLACE, not AND — a strict level no longer denies when the flag is on; a weak level no longer allows when the flag is off). - glob/manager_server.py: pure predicate is_dedicated_install_allowed (flag AND loopback, request-time args.listen); REPLACE gates at /customnode/install/git_url and /customnode/install/pip; batch unknown-URL arm routes through the same full predicate at the risky position (loopback term is load-bearing — the middle entry gate has no network-position term; the entry gate itself stays in force); unknown-pip in batch stays unconditionally blocked; new SECURITY_MESSAGE_FLAG_* denial constants name the responsible flag; security_403_response gains flag_token (comfyui_outdated keeps precedence) - glob/manager_core.py: register both keys (read via get_bool default-false, write list, exception fallback); "true"-only truthy; restart-only activation - js/common.js: 403 dialog copy names the responsible flag at the two install call sites - README.md: security-policy docs for both flags (per-surface scope incl. the batch entry-gate qualifier, REPLACE decoupling, loopback bound, opt-in config snippet, default-deny + migration note); stale tier lists corrected against the actual gates - CHANGELOG.md: opt-in migration note + accepted residual risk (flags bypass the forced-strong outdated-ComfyUI hardening on loopback, opt-in only), decoupling claim qualified for the batch entry gate Tests: unit suite (predicate truth table, REPLACE litmus both directions, AST binding-proofs against live handlers, subprocess-isolated config contract) plus a real-server E2E suite that mounts the Manager-under-test via git worktree (exact-SHA pin, detached) against a real ComfyUI and exercises both flag surfaces and both arms — deny arms (403 + flag-naming body/log + no install artifact), git-URL allow arm (real clone), pip allow arm as a two-phase reservation oracle — with zero-residual self-clean. Module skips without E2E_COMFYUI_ROOT; unit suite unaffected. The manager-v4 branch ships the identical policy (shared invariants + config contract); this tree uses the degraded predicate 'flag AND loopback' (no personal_cloud-equivalent mode here). * bump version to v3.41
102 lines
3.6 KiB
Bash
Executable File
102 lines
3.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# stop_comfyui.sh — Graceful ComfyUI shutdown (T3, spec §1.3 stop contract).
|
|
#
|
|
# Donor mirror: SIGTERM -> 10s grace -> SIGKILL -> port-pattern pkill
|
|
# fallback -> port-free verify (incl. the legacy-PID-file warning from
|
|
# the donor WI-CC cross-port-kill incident).
|
|
#
|
|
# Input env vars:
|
|
# E2E_COMFYUI_ROOT — (required) path to the E2E environment
|
|
# PORT — ComfyUI port (default: 8189)
|
|
#
|
|
# Exit: 0=stopped, 1=failed
|
|
|
|
set -euo pipefail
|
|
|
|
PORT="${PORT:-8189}"
|
|
GRACE_PERIOD=10
|
|
|
|
log() { echo "[stop_comfyui] $*"; }
|
|
err() { echo "[stop_comfyui] ERROR: $*" >&2; }
|
|
die() { err "$@"; exit 1; }
|
|
|
|
[[ -n "${E2E_COMFYUI_ROOT:-}" ]] || die "E2E_COMFYUI_ROOT is not set"
|
|
|
|
# Ownership guard: only signal a PID whose cmdline references THIS E2E root.
|
|
# On shared runners a bare "main.py --port N" pattern (or a reused PID) could
|
|
# otherwise match an unrelated process; the launcher invokes
|
|
# "$E2E_COMFYUI_ROOT/venv/bin/python $E2E_COMFYUI_ROOT/comfyui/main.py", so the
|
|
# root path is always present in our process's cmdline.
|
|
belongs_to_root() {
|
|
local pid="$1"
|
|
[[ -n "$pid" && -r "/proc/$pid/cmdline" ]] || return 1
|
|
tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null | grep -qF "$E2E_COMFYUI_ROOT"
|
|
}
|
|
|
|
# PIDs currently listening on PORT (deduped).
|
|
listener_pids() {
|
|
ss -tlnp 2>/dev/null | grep ":${PORT}\b" | grep -oE 'pid=[0-9]+' | cut -d= -f2 | sort -u
|
|
}
|
|
|
|
PID_FILE="$E2E_COMFYUI_ROOT/logs/comfyui.${PORT}.pid"
|
|
LEGACY_PID_FILE="$E2E_COMFYUI_ROOT/logs/comfyui.pid"
|
|
if [[ -f "$LEGACY_PID_FILE" ]] && [[ ! -f "$PID_FILE" ]]; then
|
|
log "WARN: found legacy unported PID file $LEGACY_PID_FILE but no ${PID_FILE}. Cross-port risk — ignoring legacy file."
|
|
fi
|
|
|
|
COMFYUI_PID=""
|
|
if [[ -f "$PID_FILE" ]]; then
|
|
COMFYUI_PID="$(cat "$PID_FILE")"
|
|
log "Read PID=$COMFYUI_PID from $PID_FILE"
|
|
fi
|
|
|
|
if [[ -n "$COMFYUI_PID" ]] && kill -0 "$COMFYUI_PID" 2>/dev/null; then
|
|
if belongs_to_root "$COMFYUI_PID"; then
|
|
log "Sending SIGTERM to PID $COMFYUI_PID..."
|
|
kill "$COMFYUI_PID" 2>/dev/null || true
|
|
elapsed=0
|
|
while kill -0 "$COMFYUI_PID" 2>/dev/null && [[ "$elapsed" -lt "$GRACE_PERIOD" ]]; do
|
|
sleep 1
|
|
elapsed=$((elapsed + 1))
|
|
done
|
|
if kill -0 "$COMFYUI_PID" 2>/dev/null; then
|
|
log "Process still alive after ${GRACE_PERIOD}s. Sending SIGKILL..."
|
|
kill -9 "$COMFYUI_PID" 2>/dev/null || true
|
|
sleep 1
|
|
fi
|
|
else
|
|
log "WARN: PID $COMFYUI_PID does NOT belong to $E2E_COMFYUI_ROOT (reused/stale PID). Refusing to kill it."
|
|
fi
|
|
fi
|
|
|
|
# Fallback: kill the port listener(s) (covers Manager-restarted processes whose
|
|
# PID differs from the recorded one) — but ONLY those verified to belong to this
|
|
# E2E root, never a broad pattern pkill that could hit unrelated CI processes.
|
|
if ss -tlnp 2>/dev/null | grep -q ":${PORT}\b"; then
|
|
log "Port $PORT still in use. Killing verified-own listener(s)..."
|
|
for pid in $(listener_pids); do
|
|
if belongs_to_root "$pid"; then
|
|
log "Sending SIGTERM to listener PID $pid..."
|
|
kill "$pid" 2>/dev/null || true
|
|
else
|
|
log "WARN: PID $pid on port $PORT is not part of $E2E_COMFYUI_ROOT — leaving it alone."
|
|
fi
|
|
done
|
|
sleep 2
|
|
for pid in $(listener_pids); do
|
|
if belongs_to_root "$pid"; then
|
|
log "Listener PID $pid still alive. Sending SIGKILL..."
|
|
kill -9 "$pid" 2>/dev/null || true
|
|
fi
|
|
done
|
|
sleep 1
|
|
fi
|
|
|
|
rm -f "$PID_FILE"
|
|
|
|
if ss -tlnp 2>/dev/null | grep -q ":${PORT}\b"; then
|
|
die "Port $PORT is still in use after shutdown"
|
|
fi
|
|
|
|
log "ComfyUI stopped."
|