加固flask看门狗

This commit is contained in:
2025-11-06 21:50:28 +08:00
parent 972c2d0d97
commit 9ed5602b86
6 changed files with 33 additions and 27 deletions

View File

@@ -18,7 +18,7 @@ class FlaskSubprocessManager:
"""Flask 子进程守护 + 看门狗 + 稳定增强""" """Flask 子进程守护 + 看门狗 + 稳定增强"""
_instance: Optional['FlaskSubprocessManager'] = None _instance: Optional['FlaskSubprocessManager'] = None
_lock = threading.Lock() _lock = threading.RLock()
def __new__(cls): def __new__(cls):
with cls._lock: with cls._lock:
@@ -42,6 +42,9 @@ class FlaskSubprocessManager:
self._fail_count = 0 self._fail_count = 0
self._last_restart_time = 0.0 self._last_restart_time = 0.0
self._watchdog_thread = None # ✅ 初始化
self._running = False # ✅ 初始化
# Windows 隐藏子窗口启动参数 # Windows 隐藏子窗口启动参数
self._si = None self._si = None
if os.name == "nt": if os.name == "nt":
@@ -175,37 +178,39 @@ class FlaskSubprocessManager:
return False return False
# ========= 停止 ========= # ========= 停止 =========
def stop(self): def stop(self, *, stop_watchdog: bool = True):
with self._lock: with self._lock:
if not self.process: return # 1) 先停子进程
try: if self.process:
if self.process.stdout: try:
self.process.stdout.flush() self.process.terminate()
time.sleep(0.1) # 让读取线程跟上 except Exception:
except Exception: pass
pass try:
self.process.wait(timeout=3)
with self._lock: except Exception:
if not self.process: pass
return if self.process and self.process.poll() is None:
pid = self.process.pid
self._log("info", f"[FlaskMgr] 正在停止子进程 PID={pid}")
try:
parent = psutil.Process(pid)
for child in parent.children(recursive=True):
try: try:
child.kill() self.process.kill()
except Exception: except Exception:
pass pass
parent.kill()
parent.wait(timeout=3)
except psutil.NoSuchProcess:
pass
except Exception as e:
self._log("error", f"[FlaskMgr] 停止子进程异常: {e}")
finally:
self.process = None self.process = None
self._stop_event.set()
# 2) 再考虑是否停 watchdog
if stop_watchdog and self._watchdog_thread and self._watchdog_thread.is_alive():
# 关键:不要 join 自己
if threading.current_thread() is not self._watchdog_thread:
self._running = False
try:
self._watchdog_thread.join(timeout=2.0)
except Exception:
pass
self._watchdog_thread = None
else:
# 如果是 watchdog 自己触发的 stop绝不 join 自己
# 也不要把句柄清空,保持线程继续执行后面的重启流程
self._running = True
# ========= 看门狗 ========= # ========= 看门狗 =========
def _monitor(self): def _monitor(self):

View File

@@ -30,6 +30,7 @@ print(f"日志目录: {LOG_DIR}")
def _run_flask_role(): def _run_flask_role():
from Module import FlaskService from Module import FlaskService
print("Flask Pid:", os.getpid())
port = int(os.getenv("FLASK_COMM_PORT", "34566")) # 固定端口的兜底仍是 34567 port = int(os.getenv("FLASK_COMM_PORT", "34566")) # 固定端口的兜底仍是 34567
app_factory = getattr(FlaskService, "create_app", None) app_factory = getattr(FlaskService, "create_app", None)
app = app_factory() if callable(app_factory) else FlaskService.app app = app_factory() if callable(app_factory) else FlaskService.app