fix(host): daemon 循环把显式 --state 透传给 recover/run-due 子进程

复核结论:应继承,不是原行为有意。daemon 本体的 pidfile/
logfile 按解析后 args.state 落盘,但旧循环只传 --config,
子进程回落到配置 state(或默认 state);CLI --state 与
配置 state 不同时,recover/run-due 跑的不是同一 state 文件。
修法:main() 解析前先记 explicit_state(argparse --state
默认 None,未给即 None);循环里仅当 explicit_state 非 None
时追加 --state,未显式给时不加、子进程按原规则解析,
与 daemon 本体一致、行为不变。daemonize() 本身只接
pidfile/logfile,不涉及 state,问题在 main() 循环里。
回归:DaemonStatePassthroughTest(2 项),旧代码上显式
项 fail、无显式项 pass,新代码上 2 项全 pass。
This commit is contained in:
muse authored and host committed 2026-11-03 02:49:25 +00:00
1 parent 1156d3c754
commit 45be478d70
2 files changed
+105 -3

No files matched your search

+14 -3
View File
@@ -2483,6 +2483,15 @@ def main():
args.progress_interval = 30
args.codex_home = args.codex_home or _resolve_path(cfg_dir, cfg.get("codex_home"))
args.codex_bin = args.codex_bin or _resolve_path(cfg_dir, cfg.get("codex_bin"))
# daemon 循环的子进程要不要带 --state,就看这里:argparse 的
# --state 默认是 None,未显式给时它就是 None;下面一行一旦
# 解析完成就分不清“CLI 给的”还是“配置/默认解析出的”了。
# 显式给的必须透传给 recover/run-due 子进程,否则子进程
# 会回落到配置文件里的 state(或默认 state),与 daemon
# 本体(pidfile/logfile 都按 args.state 落盘)跑的不是同
# 一个 state 文件。未显式给时不加 --state,子进程按原
# 规则自行解析,结果与 daemon 本体一致,行为不变。
explicit_state = args.state
args.state = args.state or _resolve_path(cfg_dir, cfg.get("state")) or DEFAULT_STATE
if args.cmd == "config":
print(json.dumps({
@@ -2713,11 +2722,13 @@ def main():
while not stop["flag"]:
ts = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print(f"{ts} daemon tick: recover + run-due", flush=True)
child_base = [sys.executable, os.path.join(HERE, "host.py"),
"--config", config_path]
if explicit_state is not None:
child_base += ["--state", explicit_state]
for subcmd in (["recover", "--older-than", "3600"], ["run-due"]):
try:
subprocess.run([sys.executable, os.path.join(HERE, "host.py"),
"--config", config_path] + subcmd,
timeout=3600)
subprocess.run(child_base + subcmd, timeout=3600)
except Exception as e:
print(f"{ts} daemon subcommand {subcmd} 失败:{e}", flush=True)
for _ in range(args.interval):