修复 EasyOCR 连续启动失败不触发重启的问题:
- 新增 _easyocr_consecutive_startup_failures 计数器,跟踪子进程无法启动的次数 - 当连续3次启动失败时,清除冷却时间并重置状态,强制重试启动 - 前2次保留冷却(预留初始化时间),第3次强制清除冷却 - 在所有重置 _easyocr_consecutive_failures 的地方同步重置启动失败计数 - 解决 EasyOCR 全程未启动但从未触发杀进程重启的问题
This commit is contained in:
+24
@@ -353,6 +353,9 @@ class MessageMonitor:
|
|||||||
# EasyOCR 连续失败计数:前2次保留子进程(预留初始化时间),第3次杀进程重来
|
# EasyOCR 连续失败计数:前2次保留子进程(预留初始化时间),第3次杀进程重来
|
||||||
self._easyocr_consecutive_failures: int = 0
|
self._easyocr_consecutive_failures: int = 0
|
||||||
self._easyocr_max_failures: int = 3 # 连续3次失败后杀进程
|
self._easyocr_max_failures: int = 3 # 连续3次失败后杀进程
|
||||||
|
# EasyOCR 连续启动失败计数:子进程无法启动时递增,达到阈值时清除冷却重试
|
||||||
|
self._easyocr_consecutive_startup_failures: int = 0
|
||||||
|
self._easyocr_max_startup_failures: int = 3 # 连续3次启动失败后清除冷却
|
||||||
# EasyOCR CUDA 错误计数:≥2 次 OOM/kernel error → 下次启动强制 CPU(防冻结)
|
# EasyOCR CUDA 错误计数:≥2 次 OOM/kernel error → 下次启动强制 CPU(防冻结)
|
||||||
self._easyocr_cuda_oom_count: int = 0
|
self._easyocr_cuda_oom_count: int = 0
|
||||||
# 引擎选择计数器
|
# 引擎选择计数器
|
||||||
@@ -420,6 +423,7 @@ class MessageMonitor:
|
|||||||
self._easyocr_retry_until = 0.0 # 清除崩溃冷却
|
self._easyocr_retry_until = 0.0 # 清除崩溃冷却
|
||||||
self._easyocr_call_count = 0
|
self._easyocr_call_count = 0
|
||||||
self._easyocr_consecutive_failures = 0 # ⭐ 清除连续超时计数(stop/急停后不残留)
|
self._easyocr_consecutive_failures = 0 # ⭐ 清除连续超时计数(stop/急停后不残留)
|
||||||
|
self._easyocr_consecutive_startup_failures = 0 # ⭐ 清除连续启动失败计数
|
||||||
|
|
||||||
# ⭐ 彻底重启时重新检测内存,尝试恢复GPU模式
|
# ⭐ 彻底重启时重新检测内存,尝试恢复GPU模式
|
||||||
# 急停/手动停止恢复时保持上次状态,不重新检测
|
# 急停/手动停止恢复时保持上次状态,不重新检测
|
||||||
@@ -491,6 +495,7 @@ class MessageMonitor:
|
|||||||
self._easyocr_retry_until = 0.0 # 清除崩溃冷却
|
self._easyocr_retry_until = 0.0 # 清除崩溃冷却
|
||||||
self._easyocr_call_count = 0
|
self._easyocr_call_count = 0
|
||||||
self._easyocr_consecutive_failures = 0 # ⭐ 清除连续超时计数(stop/急停后不残留)
|
self._easyocr_consecutive_failures = 0 # ⭐ 清除连续超时计数(stop/急停后不残留)
|
||||||
|
self._easyocr_consecutive_startup_failures = 0 # ⭐ 清除连续启动失败计数
|
||||||
self._easyocr_cuda_oom_count = 0 # 重启后重新评估 GPU/CPU
|
self._easyocr_cuda_oom_count = 0 # 重启后重新评估 GPU/CPU
|
||||||
|
|
||||||
# 释放钩子回调引用(防止 GC 延迟导致卸载后崩溃)
|
# 释放钩子回调引用(防止 GC 延迟导致卸载后崩溃)
|
||||||
@@ -658,6 +663,7 @@ class MessageMonitor:
|
|||||||
self._easyocr_retry_until = 0.0 # 清除崩溃冷却
|
self._easyocr_retry_until = 0.0 # 清除崩溃冷却
|
||||||
self._easyocr_call_count = 0
|
self._easyocr_call_count = 0
|
||||||
self._easyocr_consecutive_failures = 0 # 清除连续超时计数
|
self._easyocr_consecutive_failures = 0 # 清除连续超时计数
|
||||||
|
self._easyocr_consecutive_startup_failures = 0 # 清除连续启动失败计数
|
||||||
self._easyocr_cuda_oom_count = 0 # 清除 CUDA 错误计数(不继承本次降级)
|
self._easyocr_cuda_oom_count = 0 # 清除 CUDA 错误计数(不继承本次降级)
|
||||||
self._last_screenshot_hash.clear()
|
self._last_screenshot_hash.clear()
|
||||||
self._ocr_unchanged.clear()
|
self._ocr_unchanged.clear()
|
||||||
@@ -1498,6 +1504,7 @@ class MessageMonitor:
|
|||||||
payload = json.loads(line)
|
payload = json.loads(line)
|
||||||
if payload.get("ready"):
|
if payload.get("ready"):
|
||||||
logger.debug("[ocr] EasyOCR 子进程就绪")
|
logger.debug("[ocr] EasyOCR 子进程就绪")
|
||||||
|
self._easyocr_consecutive_startup_failures = 0 # 成功启动,重置启动失败计数
|
||||||
return True
|
return True
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
@@ -1529,6 +1536,21 @@ class MessageMonitor:
|
|||||||
import base64
|
import base64
|
||||||
|
|
||||||
if not self._ensure_easyocr_subprocess():
|
if not self._ensure_easyocr_subprocess():
|
||||||
|
# ⭐ 连续启动失败计数:子进程无法启动时递增,达到阈值时清除冷却重试
|
||||||
|
self._easyocr_consecutive_startup_failures += 1
|
||||||
|
if self._easyocr_consecutive_startup_failures >= self._easyocr_max_startup_failures:
|
||||||
|
logger.warning(f"[ocr] EasyOCR 连续{self._easyocr_consecutive_startup_failures}次启动失败,"
|
||||||
|
f"清除冷却({int(self._easyocr_retry_until - time.time())}s)并重置状态,强制重试")
|
||||||
|
# 清除冷却时间,强制重试启动
|
||||||
|
self._easyocr_retry_until = 0.0
|
||||||
|
# 重置进程状态
|
||||||
|
self._easyocr_proc = None
|
||||||
|
self._easyocr_broken = False
|
||||||
|
# 重置计数器(避免无限循环)
|
||||||
|
self._easyocr_consecutive_startup_failures = 0
|
||||||
|
else:
|
||||||
|
logger.debug(f"[ocr] EasyOCR 第{self._easyocr_consecutive_startup_failures}次启动失败,"
|
||||||
|
f"保留冷却({int(self._easyocr_retry_until - time.time())}s)")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -1581,6 +1603,7 @@ class MessageMonitor:
|
|||||||
pass
|
pass
|
||||||
self._easyocr_proc = None
|
self._easyocr_proc = None
|
||||||
self._easyocr_consecutive_failures = 0
|
self._easyocr_consecutive_failures = 0
|
||||||
|
self._easyocr_consecutive_startup_failures = 0 # 重置启动失败计数
|
||||||
else:
|
else:
|
||||||
logger.debug(f"[ocr] EasyOCR 第{self._easyocr_consecutive_failures}次超时({timeout}s),保留子进程不杀")
|
logger.debug(f"[ocr] EasyOCR 第{self._easyocr_consecutive_failures}次超时({timeout}s),保留子进程不杀")
|
||||||
return None
|
return None
|
||||||
@@ -1596,6 +1619,7 @@ class MessageMonitor:
|
|||||||
if result.get("ok"):
|
if result.get("ok"):
|
||||||
# 成功 → 重置连续失败计数
|
# 成功 → 重置连续失败计数
|
||||||
self._easyocr_consecutive_failures = 0
|
self._easyocr_consecutive_failures = 0
|
||||||
|
self._easyocr_consecutive_startup_failures = 0 # 成功启动,重置启动失败计数
|
||||||
# 计数 + 主动重启:EasyOCR GPU 内存泄漏累积 → OOM → 冻结
|
# 计数 + 主动重启:EasyOCR GPU 内存泄漏累积 → OOM → 冻结
|
||||||
self._easyocr_call_count += 1
|
self._easyocr_call_count += 1
|
||||||
if self._easyocr_call_count >= self._easyocr_max_calls:
|
if self._easyocr_call_count >= self._easyocr_max_calls:
|
||||||
|
|||||||
Reference in New Issue
Block a user