加固flask看门狗
This commit is contained in:
@@ -18,7 +18,7 @@ class FlaskSubprocessManager:
|
||||
"""Flask 子进程守护 + 看门狗 + 稳定增强"""
|
||||
|
||||
_instance: Optional['FlaskSubprocessManager'] = None
|
||||
_lock = threading.Lock()
|
||||
_lock = threading.RLock()
|
||||
|
||||
def __new__(cls):
|
||||
with cls._lock:
|
||||
@@ -42,6 +42,9 @@ class FlaskSubprocessManager:
|
||||
self._fail_count = 0
|
||||
self._last_restart_time = 0.0
|
||||
|
||||
self._watchdog_thread = None # ✅ 初始化
|
||||
self._running = False # ✅ 初始化
|
||||
|
||||
# Windows 隐藏子窗口启动参数
|
||||
self._si = None
|
||||
if os.name == "nt":
|
||||
@@ -175,37 +178,39 @@ class FlaskSubprocessManager:
|
||||
return False
|
||||
|
||||
# ========= 停止 =========
|
||||
def stop(self):
|
||||
def stop(self, *, stop_watchdog: bool = True):
|
||||
with self._lock:
|
||||
if not self.process: return
|
||||
try:
|
||||
if self.process.stdout:
|
||||
self.process.stdout.flush()
|
||||
time.sleep(0.1) # 让读取线程跟上
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
with self._lock:
|
||||
if not self.process:
|
||||
return
|
||||
pid = self.process.pid
|
||||
self._log("info", f"[FlaskMgr] 正在停止子进程 PID={pid}")
|
||||
try:
|
||||
parent = psutil.Process(pid)
|
||||
for child in parent.children(recursive=True):
|
||||
# 1) 先停子进程
|
||||
if self.process:
|
||||
try:
|
||||
self.process.terminate()
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
self.process.wait(timeout=3)
|
||||
except Exception:
|
||||
pass
|
||||
if self.process and self.process.poll() is None:
|
||||
try:
|
||||
child.kill()
|
||||
self.process.kill()
|
||||
except Exception:
|
||||
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._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):
|
||||
|
||||
@@ -30,6 +30,7 @@ print(f"日志目录: {LOG_DIR}")
|
||||
|
||||
def _run_flask_role():
|
||||
from Module import FlaskService
|
||||
print("Flask Pid:", os.getpid())
|
||||
port = int(os.getenv("FLASK_COMM_PORT", "34566")) # 固定端口的兜底仍是 34567
|
||||
app_factory = getattr(FlaskService, "create_app", None)
|
||||
app = app_factory() if callable(app_factory) else FlaskService.app
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user