diff --git a/Html/apps/__init__.py b/Html/apps/__init__.py
index 00ed968..82edac9 100644
--- a/Html/apps/__init__.py
+++ b/Html/apps/__init__.py
@@ -1,10 +1,38 @@
import logging
from flask import Flask
from .config import Config
-from .extensions import init_extensions, register_namespaces
+from .extensions import init_extensions, register_namespaces, close_extensions
from .views import register_blueprints
+import atexit
+import logging
+import signal
+import threading
+_shutdown_once = threading.Event()
+def _graceful_shutdown(app: Flask, signum: str = "atexit"):
+ # 防止重复执行
+ if _shutdown_once.is_set():
+ return
+ _shutdown_once.set()
+
+ app.logger.info("Shutting down gracefully (%s)...", signum)
+ try:
+ close_extensions()
+ finally:
+ app.logger.info("Cleanup finished (%s).", signum)
+
+def _bind_signals(app: Flask):
+ def handler(sig, frame):
+ _graceful_shutdown(app, signum=sig)
+ # 不要在这里强行 os._exit(0),让外层管理器决定何时真正退出
+ for s in (signal.SIGINT, signal.SIGTERM, getattr(signal, "SIGQUIT", None)):
+ if s is not None:
+ try:
+ signal.signal(s, handler)
+ except Exception:
+ # 某些环境不能重绑定(如部分 WSGI 容器内),忽略
+ pass
def create_app(config_object: type = Config) -> Flask:
app = Flask(__name__, template_folder="templates", static_folder="static")
@@ -31,4 +59,9 @@ def create_app(config_object: type = Config) -> Flask:
def healthz():
return {"status": "ok"}
+
+ # 绑定退出钩子(开发/简单部署环境很有用)
+ atexit.register(_graceful_shutdown, app, "atexit")
+ _bind_signals(app)
+
return app
diff --git a/Html/apps/extension_ase/ase_client/manager.py b/Html/apps/extension_ase/ase_client/manager.py
index 0841273..466bfd6 100644
--- a/Html/apps/extension_ase/ase_client/manager.py
+++ b/Html/apps/extension_ase/ase_client/manager.py
@@ -247,4 +247,6 @@ class ChatManager:
with self._lock:
keys = list(self._procs.keys())
for k in keys:
- self.stop(k)
\ No newline at end of file
+ self.stop(k)
+
+
\ No newline at end of file
diff --git a/Html/apps/extensions.py b/Html/apps/extensions.py
index 2c6aaba..d55cc80 100644
--- a/Html/apps/extensions.py
+++ b/Html/apps/extensions.py
@@ -9,6 +9,7 @@ from flask_pymongo import PyMongo
from qcloud_cos import CosConfig
from qcloud_cos import CosS3Client
+from typing import Optional
mongo = PyMongo()
@@ -76,4 +77,15 @@ def register_namespaces(app):
# 延迟导入以避免循环
from .sockets.namespaces import VSCodeNamespace, AgentNamespace
socketio.on_namespace(VSCodeNamespace("/vscode"))
- socketio.on_namespace(AgentNamespace("/agent"))
\ No newline at end of file
+ socketio.on_namespace(AgentNamespace("/agent"))
+
+
+def close_extensions():
+ # 按“最可能阻塞”的优先级依次停止
+ try:
+ if user_uuid2chatmanager:
+ for uuid in user_uuid2chatmanager:
+ user_uuid2chatmanager[uuid].disconnect(uuid)
+ except Exception as e:
+ print("Failed to shutdown scheduler: %s", e)
+
\ No newline at end of file