fix: add SIGALRM 120s hard timeout to price_monitor lock

price_monitor.py 进程锁无硬超时,LLM策略重评耗时9-10分钟时
锁文件阻止后续*/2 cron执行,造成10分钟监控盲区。

新增:
- _handle_sigalrm: SIGALRM处理器,自动清理锁后退出
- signal.alarm(120): 获锁后设120s硬上限
- signal.alarm(0): 正常完成时取消定时器
This commit is contained in:
知微
2026-07-21 11:29:06 +08:00
parent f6d10a41af
commit c180129a1a
+11
View File
@@ -407,10 +407,17 @@ def _handle_sigterm(signum, frame):
_cleanup_lock() _cleanup_lock()
sys.exit(0) sys.exit(0)
def _handle_sigalrm(signum, frame):
"""收到SIGALRM强制超时时清理锁文件后退出"""
_cleanup_lock()
print(f"[TIMEOUT] 本轮执行超时({signum}s),已清理锁文件", file=sys.stderr, flush=True)
sys.exit(0)
def run_once(round_label=""): def run_once(round_label=""):
"""执行一轮完整的监控流程""" """执行一轮完整的监控流程"""
import os, signal # 必须在开头import,否则os变量会被后面的局部import绑定覆盖 import os, signal # 必须在开头import,否则os变量会被后面的局部import绑定覆盖
signal.signal(signal.SIGTERM, _handle_sigterm) signal.signal(signal.SIGTERM, _handle_sigterm)
signal.signal(signal.SIGALRM, _handle_sigalrm)
os.nice(10) # 降低优先级,避免与DB其他写操作抢占 os.nice(10) # 降低优先级,避免与DB其他写操作抢占
# ── 进程锁:同一时间只跑一个实例 ── # ── 进程锁:同一时间只跑一个实例 ──
_lk = "/tmp/price_monitor.lock" _lk = "/tmp/price_monitor.lock"
@@ -425,6 +432,7 @@ def run_once(round_label=""):
pass pass
with open(_lk, "w") as _f: with open(_lk, "w") as _f:
_f.write(str(os.getpid())) _f.write(str(os.getpid()))
signal.alarm(120) # 硬上限120s,超时自动清理锁退出
label = f" [{round_label}]" if round_label else "" label = f" [{round_label}]" if round_label else ""
start = time.time() start = time.time()
@@ -745,6 +753,9 @@ def run_once(round_label=""):
# 输出耗时 # 输出耗时
print(f"{label} {elapsed:.1f}s", flush=True) print(f"{label} {elapsed:.1f}s", flush=True)
# 取消超时定时器(正常完成)
signal.alarm(0)
# 清理进程锁 # 清理进程锁
try: try:
os.remove("/tmp/price_monitor.lock") os.remove("/tmp/price_monitor.lock")