86 lines
2.3 KiB
Python
Executable File
86 lines
2.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""
|
||
stop.py — Stop the AI Video Upscaler web application.
|
||
|
||
Usage:
|
||
python stop.py
|
||
"""
|
||
|
||
import os
|
||
import signal
|
||
import sys
|
||
import time
|
||
|
||
# ── Paths ────────────────────────────────────────────────────────────────────
|
||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||
PID_FILE = os.path.join(BASE_DIR, ".uvicorn.pid")
|
||
|
||
|
||
def _is_running(pid: int) -> bool:
|
||
"""Check whether a process with the given PID is still alive and is our server."""
|
||
try:
|
||
os.kill(pid, 0)
|
||
except OSError:
|
||
return False
|
||
|
||
# Check /proc/{pid}/cmdline to verify it's our server process
|
||
try:
|
||
cmdline_path = f"/proc/{pid}/cmdline"
|
||
if os.path.exists(cmdline_path):
|
||
with open(cmdline_path, "r") as f:
|
||
cmdline = f.read()
|
||
# Check for indicators of our server
|
||
return "uvicorn" in cmdline or "app.main" in cmdline
|
||
except Exception:
|
||
pass
|
||
# If we can't read cmdline, default to True (safer fallback)
|
||
return True
|
||
|
||
|
||
def stop() -> None:
|
||
if not os.path.isfile(PID_FILE):
|
||
print("ℹ No server appears to be running (no pidfile found).")
|
||
return
|
||
|
||
try:
|
||
pid = int(open(PID_FILE).read().strip())
|
||
except (ValueError, OSError):
|
||
print("⚠ Pidfile exists but is unreadable. Removing it.")
|
||
os.remove(PID_FILE)
|
||
return
|
||
|
||
if not _is_running(pid):
|
||
print(f"ℹ Server (PID {pid}) is not running. Cleaning up pidfile.")
|
||
os.remove(PID_FILE)
|
||
return
|
||
|
||
print(f"🛑 Stopping server (PID {pid}) …")
|
||
|
||
# Graceful shutdown (SIGTERM)
|
||
os.kill(pid, signal.SIGTERM)
|
||
|
||
# Wait up to 10 seconds for graceful exit
|
||
for i in range(20):
|
||
time.sleep(0.5)
|
||
if not _is_running(pid):
|
||
break
|
||
else:
|
||
# Force kill if still alive
|
||
print(f" ⚠ Server didn't stop gracefully, sending SIGKILL …")
|
||
os.kill(pid, signal.SIGKILL)
|
||
time.sleep(0.5)
|
||
|
||
# Clean up pidfile
|
||
if os.path.isfile(PID_FILE):
|
||
os.remove(PID_FILE)
|
||
|
||
if _is_running(pid):
|
||
print(f"❌ Failed to stop server (PID {pid}).")
|
||
sys.exit(1)
|
||
else:
|
||
print(f"✅ Server stopped.")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
stop()
|