fix(chv): execd 单元 KillMode=process(构建 #6 驱动实证)
缺 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。
This commit is contained in:
1 parent
42adbd047f
commit
6a65c94254
2 files changed
+27
-1
No files matched your search
+8
-1
@@ -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 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 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 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 "[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')
|
--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):文件在仓库里存在时拷入
|
# P1 交接(Muse P1 的 vsock_notify.py):文件在仓库里存在时拷入
|
||||||
|
|||||||
@@ -451,6 +451,25 @@ class BuildWiringTest(unittest.TestCase):
|
|||||||
'stat -c %a /etc/systemd/network/79-chv-cell.network',
|
'stat -c %a /etc/systemd/network/79-chv-cell.network',
|
||||||
text)
|
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):
|
def test_lockfile_and_buildinfo_declare_services(self):
|
||||||
spec = importlib.util.spec_from_file_location(
|
spec = importlib.util.spec_from_file_location(
|
||||||
"stage2_buildinfo",
|
"stage2_buildinfo",
|
||||||
|
|||||||
Reference in new issue
Block a user