fix: close bare open() in host.py and ResourceWarning in test_host_thread_cli
- host.py: 7 one-shot reads switched to with open (run_health_check pidfile, daemon-status pid/log, daemon-stop pid, daemon old pid, interrupt poll state, parallel jobs); read content, encoding args and error semantics unchanged. - tests/test_host_thread_cli.py: test_old_archive_unchanged state read switched to with open; added a warnings-capture assertion scoped to the state read so a regression fails the test. - Intentionally untouched: daemonize log handle (daemon-lifetime dup2 target) and the two _load_config_file / init sites owned by PR #266.
This commit is contained in:
1 parent
72d343b2c7
commit
436a92ba1d
2 files changed
+29
-9
No files matched your search
@@ -1120,7 +1120,8 @@ def run_health_check(state_path, cfg, codex_bin, codex_home, approval,
|
|||||||
checks["daemon_pidfile"] = pidfile
|
checks["daemon_pidfile"] = pidfile
|
||||||
if os.path.exists(pidfile):
|
if os.path.exists(pidfile):
|
||||||
try:
|
try:
|
||||||
pid = int(open(pidfile).read().strip())
|
with open(pidfile) as f:
|
||||||
|
pid = int(f.read().strip())
|
||||||
os.kill(pid, 0)
|
os.kill(pid, 0)
|
||||||
checks["daemon_alive"] = True
|
checks["daemon_alive"] = True
|
||||||
checks["daemon_pid"] = pid
|
checks["daemon_pid"] = pid
|
||||||
@@ -2707,7 +2708,8 @@ def main():
|
|||||||
pid = None
|
pid = None
|
||||||
if os.path.exists(pidfile):
|
if os.path.exists(pidfile):
|
||||||
try:
|
try:
|
||||||
pid = int(open(pidfile).read().strip())
|
with open(pidfile) as f:
|
||||||
|
pid = int(f.read().strip())
|
||||||
os.kill(pid, 0)
|
os.kill(pid, 0)
|
||||||
alive = True
|
alive = True
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -2715,7 +2717,8 @@ def main():
|
|||||||
tail = ""
|
tail = ""
|
||||||
if os.path.exists(logfile):
|
if os.path.exists(logfile):
|
||||||
try:
|
try:
|
||||||
tail = "\n".join(open(logfile).read().splitlines()[-5:])
|
with open(logfile) as f:
|
||||||
|
tail = "\n".join(f.read().splitlines()[-5:])
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
print(json.dumps({"alive": alive, "pid": pid, "pidfile": pidfile,
|
print(json.dumps({"alive": alive, "pid": pid, "pidfile": pidfile,
|
||||||
@@ -2728,7 +2731,8 @@ def main():
|
|||||||
print("daemon 未运行(无 pidfile)")
|
print("daemon 未运行(无 pidfile)")
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
pid = int(open(pidfile).read().strip())
|
with open(pidfile) as f:
|
||||||
|
pid = int(f.read().strip())
|
||||||
except Exception:
|
except Exception:
|
||||||
print("pidfile 损坏,直接删除")
|
print("pidfile 损坏,直接删除")
|
||||||
os.remove(pidfile)
|
os.remove(pidfile)
|
||||||
@@ -2758,7 +2762,8 @@ def main():
|
|||||||
if not args.foreground:
|
if not args.foreground:
|
||||||
if os.path.exists(pidfile):
|
if os.path.exists(pidfile):
|
||||||
try:
|
try:
|
||||||
old_pid = int(open(pidfile).read().strip())
|
with open(pidfile) as f:
|
||||||
|
old_pid = int(f.read().strip())
|
||||||
os.kill(old_pid, 0)
|
os.kill(old_pid, 0)
|
||||||
print(f"daemon 已在运行:pid {old_pid},先 daemon-stop 再起")
|
print(f"daemon 已在运行:pid {old_pid},先 daemon-stop 再起")
|
||||||
return
|
return
|
||||||
@@ -3272,8 +3277,8 @@ def main():
|
|||||||
for _ in range(10):
|
for _ in range(10):
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
try:
|
try:
|
||||||
cur = json.load(open(args.state,
|
with open(args.state, encoding="utf-8") as f:
|
||||||
encoding="utf-8"))
|
cur = json.load(f)
|
||||||
if (cur.get("tasks", {}).get(args.task, {})
|
if (cur.get("tasks", {}).get(args.task, {})
|
||||||
.get("status") == "interrupted"):
|
.get("status") == "interrupted"):
|
||||||
print(f"interrupt {args.task}: 属主已响应,"
|
print(f"interrupt {args.task}: 属主已响应,"
|
||||||
@@ -3424,7 +3429,8 @@ def main():
|
|||||||
last_turn_status=t.get("goal_last_turn_status"),
|
last_turn_status=t.get("goal_last_turn_status"),
|
||||||
last_turn_text=last_result.get("text", "") or "")
|
last_turn_text=last_result.get("text", "") or "")
|
||||||
elif args.cmd == "parallel":
|
elif args.cmd == "parallel":
|
||||||
jobs = json.load(open(args.jobs))
|
with open(args.jobs) as f:
|
||||||
|
jobs = json.load(f)
|
||||||
# 依赖 + 优先级:先拓扑排序,缺依赖/成环直接报错不跑;
|
# 依赖 + 优先级:先拓扑排序,缺依赖/成环直接报错不跑;
|
||||||
# 按波次派发 + 跑:依赖都 completed 的任务才进本波,
|
# 按波次派发 + 跑:依赖都 completed 的任务才进本波,
|
||||||
# 依赖 failed/skipped 的任务标 skipped 不跑,避免在坏
|
# 依赖 failed/skipped 的任务标 skipped 不跑,避免在坏
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
import gc
|
||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
import warnings
|
||||||
from contextlib import redirect_stdout
|
from contextlib import redirect_stdout
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
import host
|
import host
|
||||||
@@ -246,7 +248,19 @@ class ThreadCliTest(unittest.TestCase):
|
|||||||
code = e.code if isinstance(e.code, int) else 1
|
code = e.code if isinstance(e.code, int) else 1
|
||||||
self.assertEqual(code, 0)
|
self.assertEqual(code, 0)
|
||||||
self.assertIn("archived t1", out.getvalue())
|
self.assertIn("archived t1", out.getvalue())
|
||||||
saved = json.loads(Path(state_path).read_text(encoding="utf-8"))
|
# 第 4 项回归:此处裸 open() 曾在 GC 时报 ResourceWarning;
|
||||||
|
# 只捕获本段读 state 的警告断言(_load_config_file 的
|
||||||
|
# 警告属 #266 轨,不在此断言范围内)。
|
||||||
|
with warnings.catch_warnings(record=True) as caught:
|
||||||
|
warnings.simplefilter("always", ResourceWarning)
|
||||||
|
with open(state_path, encoding="utf-8") as f:
|
||||||
|
saved = json.load(f)
|
||||||
|
gc.collect()
|
||||||
|
self.assertEqual(
|
||||||
|
[w for w in caught
|
||||||
|
if issubclass(w.category, ResourceWarning)
|
||||||
|
and "host-state.json" in str(w.message)],
|
||||||
|
[])
|
||||||
self.assertEqual(saved["tasks"]["t1"]["status"], "archived")
|
self.assertEqual(saved["tasks"]["t1"]["status"], "archived")
|
||||||
calls = self._calls_before_close(fake)
|
calls = self._calls_before_close(fake)
|
||||||
self.assertEqual(calls, [("archive", "th-1")])
|
self.assertEqual(calls, [("archive", "th-1")])
|
||||||
|
|||||||
Reference in new issue
Block a user