fix: resource leaks and connection safety
- Use context managers for all SQLite connections - Add temp file cleanup in report download endpoint - Add finally blocks for file handle cleanup in simulation runner
This commit is contained in:
parent
985f89f49a
commit
7d76f663dc
|
|
@ -6,7 +6,7 @@ Report API路由
|
|||
import os
|
||||
import traceback
|
||||
import threading
|
||||
from flask import request, jsonify, send_file
|
||||
from flask import request, jsonify, send_file, after_this_request
|
||||
|
||||
from . import report_bp
|
||||
from ..config import Config
|
||||
|
|
@ -415,6 +415,15 @@ def download_report(report_id: str):
|
|||
f.write(report.markdown_content)
|
||||
temp_path = f.name
|
||||
|
||||
@after_this_request
|
||||
def cleanup(response):
|
||||
try:
|
||||
if temp_path and os.path.exists(temp_path):
|
||||
os.unlink(temp_path)
|
||||
except OSError:
|
||||
pass
|
||||
return response
|
||||
|
||||
return send_file(
|
||||
temp_path,
|
||||
as_attachment=True,
|
||||
|
|
|
|||
|
|
@ -2016,7 +2016,7 @@ def get_simulation_posts(simulation_id: str):
|
|||
})
|
||||
|
||||
import sqlite3
|
||||
conn = sqlite3.connect(db_path)
|
||||
with sqlite3.connect(db_path) as conn:
|
||||
conn.row_factory = sqlite3.Row
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
|
@ -2036,8 +2036,6 @@ def get_simulation_posts(simulation_id: str):
|
|||
posts = []
|
||||
total = 0
|
||||
|
||||
conn.close()
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": {
|
||||
|
|
@ -2089,7 +2087,7 @@ def get_simulation_comments(simulation_id: str):
|
|||
})
|
||||
|
||||
import sqlite3
|
||||
conn = sqlite3.connect(db_path)
|
||||
with sqlite3.connect(db_path) as conn:
|
||||
conn.row_factory = sqlite3.Row
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
|
@ -2113,8 +2111,6 @@ def get_simulation_comments(simulation_id: str):
|
|||
except sqlite3.OperationalError:
|
||||
comments = []
|
||||
|
||||
conn.close()
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": {
|
||||
|
|
|
|||
|
|
@ -426,6 +426,7 @@ class SimulationRunner:
|
|||
main_log_path = os.path.join(sim_dir, "simulation.log")
|
||||
main_log_file = open(main_log_path, 'w', encoding='utf-8')
|
||||
|
||||
try:
|
||||
# 设置子进程环境变量,确保 Windows 上使用 UTF-8 编码
|
||||
# 这可以修复第三方库(如 OASIS)读取文件时未指定编码的问题
|
||||
env = os.environ.copy()
|
||||
|
|
@ -445,6 +446,9 @@ class SimulationRunner:
|
|||
env=env, # 传递带有 UTF-8 设置的环境变量
|
||||
start_new_session=True, # 创建新进程组,确保服务器关闭时能终止所有相关进程
|
||||
)
|
||||
except Exception:
|
||||
main_log_file.close()
|
||||
raise
|
||||
|
||||
# 保存文件句柄以便后续关闭
|
||||
cls._stdout_files[simulation_id] = main_log_file
|
||||
|
|
@ -1667,7 +1671,7 @@ class SimulationRunner:
|
|||
results = []
|
||||
|
||||
try:
|
||||
conn = sqlite3.connect(db_path)
|
||||
with sqlite3.connect(db_path) as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
if agent_id is not None:
|
||||
|
|
@ -1701,8 +1705,6 @@ class SimulationRunner:
|
|||
"platform": platform_name
|
||||
})
|
||||
|
||||
conn.close()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"读取Interview历史失败 ({platform_name}): {e}")
|
||||
|
||||
|
|
|
|||
|
|
@ -528,7 +528,7 @@ class ParallelIPCHandler:
|
|||
return result
|
||||
|
||||
try:
|
||||
conn = sqlite3.connect(db_path)
|
||||
with sqlite3.connect(db_path) as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 查询最新的Interview记录
|
||||
|
|
@ -550,8 +550,6 @@ class ParallelIPCHandler:
|
|||
except json.JSONDecodeError:
|
||||
result["response"] = info_json
|
||||
|
||||
conn.close()
|
||||
|
||||
except Exception as e:
|
||||
print(f" 读取Interview结果失败: {e}")
|
||||
|
||||
|
|
@ -679,7 +677,7 @@ def fetch_new_actions_from_db(
|
|||
return actions, new_last_rowid
|
||||
|
||||
try:
|
||||
conn = sqlite3.connect(db_path)
|
||||
with sqlite3.connect(db_path) as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 使用 rowid 来追踪已处理的记录(rowid 是 SQLite 的内置自增字段)
|
||||
|
|
@ -738,8 +736,6 @@ def fetch_new_actions_from_db(
|
|||
'action_type': action_type,
|
||||
'action_args': simplified_args,
|
||||
})
|
||||
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
print(f"读取数据库动作失败: {e}")
|
||||
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@ class IPCHandler:
|
|||
return result
|
||||
|
||||
try:
|
||||
conn = sqlite3.connect(db_path)
|
||||
with sqlite3.connect(db_path) as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 查询最新的Interview记录
|
||||
|
|
@ -333,8 +333,6 @@ class IPCHandler:
|
|||
except json.JSONDecodeError:
|
||||
result["response"] = info_json
|
||||
|
||||
conn.close()
|
||||
|
||||
except Exception as e:
|
||||
print(f" 读取Interview结果失败: {e}")
|
||||
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@ class IPCHandler:
|
|||
return result
|
||||
|
||||
try:
|
||||
conn = sqlite3.connect(db_path)
|
||||
with sqlite3.connect(db_path) as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 查询最新的Interview记录
|
||||
|
|
@ -333,8 +333,6 @@ class IPCHandler:
|
|||
except json.JSONDecodeError:
|
||||
result["response"] = info_json
|
||||
|
||||
conn.close()
|
||||
|
||||
except Exception as e:
|
||||
print(f" 读取Interview结果失败: {e}")
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue