From 6a65c942546da0bbe8f3d60f746776b66a81b7d8 Mon Sep 17 00:00:00 2001 From: host Date: Sat, 7 Nov 2026 18:10:29 +0000 Subject: [PATCH] =?UTF-8?q?fix(chv):=20execd=20=E5=8D=95=E5=85=83=20KillMo?= =?UTF-8?q?de=3Dprocess=EF=BC=88=E6=9E=84=E5=BB=BA=20#6=20=E9=A9=B1?= =?UTF-8?q?=E5=8A=A8=E5=AE=9E=E8=AF=81=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 缺 KillMode 时 systemd 默认 control-group,kill -9 execd 主进程 后重启会 SIGTERM 整个 cgroup,sleep 任务同 pid 存活的要求被破、 新 execd 认领时 pid 已死记 unknown,驱动 kill 相断言失败。 KillMode=process 只信号主进程,任务在重启后同 pid 存活认领; stop 仍干净停 daemon 本身。回归测试 BuildWiringTest.test_build_sh_execd_unit_keeps_tasks_on_restart。 --- chv-guest/build.sh | 9 ++++++++- cloud/tests/test_chv_opt_stage2.py | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/chv-guest/build.sh b/chv-guest/build.sh index 928f13a..300e59f 100755 --- a/chv-guest/build.sh +++ b/chv-guest/build.sh @@ -325,7 +325,14 @@ VC_ARGS=(-a "$OUT/disk.raw" --run-command 'printf "[Unit]\nDescription=CHV cell broker (Muse P2)\nAfter=network.target\n\n[Service]\nType=simple\nExecStart=/usr/bin/python3 /usr/local/bin/chv-broker\nRestart=on-failure\nRestartSec=2\n\n[Install]\nWantedBy=multi-user.target\n" > /etc/systemd/system/chv-broker.service' --run-command 'printf "[Unit]\nDescription=CHV browser sub-agent (Muse P2)\nAfter=network.target\n\n[Service]\nType=simple\nUser=chv-browser\nGroup=chv-browser\nExecStart=/usr/bin/python3 /usr/local/bin/chv-browser\nRestart=on-failure\nRestartSec=2\n\n[Install]\nWantedBy=multi-user.target\n" > /etc/systemd/system/chv-browser.service' --run-command 'printf "[Unit]\nDescription=CHV guest runtime daemon (stage 2: heartbeat/resources/snapshot)\nAfter=network.target\n\n[Service]\nType=simple\nExecStart=/usr/bin/python3 /usr/local/bin/chv-daemon\nRestart=always\nRestartSec=2\n\n[Install]\nWantedBy=multi-user.target\n" > /etc/systemd/system/chv-daemon.service' - --run-command 'printf "[Unit]\nDescription=CHV guest exec daemon (stage 2: shell/files/codex hosting)\nAfter=network.target\n\n[Service]\nType=simple\nExecStart=/usr/bin/python3 /usr/local/bin/chv-execd\nRestart=always\nRestartSec=2\n\n[Install]\nWantedBy=multi-user.target\n" > /etc/systemd/system/chv-execd.service' + # 构建 #6 驱动实证(2026-11-08):execd 单元缺 KillMode 时默认 + # control-group,kill -9 主进程后 systemd 重启会 SIGTERM 整个 + # cgroup,sleep 任务(同 pid 应存活)被连带杀死,新 execd 认领 + # 时 pid 已死、记 unknown,驱动 kill 相断言失败。KillMode=process + # 只信号主进程,任务在 execd 重启后同 pid 存活、按登记认领; + # systemctl stop 仍干净停掉 daemon 本身,任务以孤儿存活、下次 + # 启动再按 pid 认领(登记落盘 /run/chv/execd-tasks.json)。 + --run-command 'printf "[Unit]\nDescription=CHV guest exec daemon (stage 2: shell/files/codex hosting)\nAfter=network.target\n\n[Service]\nType=simple\nExecStart=/usr/bin/python3 /usr/local/bin/chv-execd\nRestart=always\nRestartSec=2\nKillMode=process\n\n[Install]\nWantedBy=multi-user.target\n" > /etc/systemd/system/chv-execd.service' --run-command 'printf "[Unit]\nDescription=CHV Gitea sync daemon (stage 2: resident pull/push loop)\nAfter=network.target\n\n[Service]\nType=simple\nUser=chv\nGroup=chv\nRuntimeDirectory=chv-syncd\nRuntimeDirectoryMode=0755\nExecStart=/usr/bin/python3 /usr/local/bin/chv-syncd\nRestart=always\nRestartSec=2\n\n[Install]\nWantedBy=multi-user.target\n" > /etc/systemd/system/chv-syncd.service' --run-command 'printf "d /run/chv 0755 root root -\nd /run/chv/shots 0755 chv-browser chv-browser -\nd /run/chv/tasks 0755 root root -\n" > /etc/tmpfiles.d/chv.conf && systemctl enable chv-broker chv-browser chv-daemon chv-execd chv-syncd || true') # P1 交接(Muse P1 的 vsock_notify.py):文件在仓库里存在时拷入 diff --git a/cloud/tests/test_chv_opt_stage2.py b/cloud/tests/test_chv_opt_stage2.py index fe32b02..588aa49 100644 --- a/cloud/tests/test_chv_opt_stage2.py +++ b/cloud/tests/test_chv_opt_stage2.py @@ -451,6 +451,25 @@ class BuildWiringTest(unittest.TestCase): 'stat -c %a /etc/systemd/network/79-chv-cell.network', text) + def test_build_sh_execd_unit_keeps_tasks_on_restart(self): + # 构建 #6 驱动实证:缺 KillMode 时 systemd 重启会杀整个 + # cgroup,sleep 任务同 pid 存活的要求被破。execd 单元须 + # KillMode=process;daemon/syncd 无长活子进程,不动。 + with open(_repo("chv-guest", "build.sh")) as fh: + text = fh.read() + execd = next( + line for line in text.splitlines() + if "chv-execd.service" in line + and "Description=CHV guest exec daemon" in line) + self.assertIn("KillMode=process", execd) + self.assertEqual(execd.count("KillMode=process"), 1) + for svc in ("chv-daemon", "chv-syncd"): + block = next( + line for line in text.splitlines() + if "%s.service" % svc in line + and "Description=" in line) + self.assertNotIn("KillMode", block) + def test_lockfile_and_buildinfo_declare_services(self): spec = importlib.util.spec_from_file_location( "stage2_buildinfo",