part 4 缺陷 1:cell 启动竞态——起步门 + init pid 轮询

RETEST3 缺陷 1:run_cell 里配网与 payload 零同步,快 payload
(run -- true)在配网完成前退出即撞墙,11 次只成 6 次。
本提交先落 helper(接线在缺陷 3 的 run_cell 重写里做):
- gate_wrapper_command():payload 包一层 sh 起步门,等
  /run/chv/.cell-gate-<machine> 出现再 exec(绝对路径
  /usr/bin/sh:volatile 单元根里 /bin 未必有)。
- find_cell_init_pid() 改带超时轮询(timeout 默认 0.0 = 单次,
  旧调用行为不变;缺目录不再直接回 None;proc_alive 回调让
  nspawn 已死时立刻回,不空等)。
新测试:CellGateTest、CellInitPidPollTest(5 个)。
This commit is contained in:
host committed 2026-11-07 10:29:13 +00:00
1 parent 179a86d655
commit fc33eed262
2 files changed
+120 -15

No files matched your search

+70
View File
@@ -742,5 +742,75 @@ class BuildDryRunTest(unittest.TestCase):
self.assertIn(needle, out, needle)
class CellGateTest(unittest.TestCase):
"""part 4:起步门包装。"""
def test_gate_wrapper_waits_then_execs(self):
wrapped = CELL.gate_wrapper_command(
["python3", "/app/host.py", "status"],
"/run/chv/.cell-gate-chv-cell-00")
self.assertEqual(wrapped[:4], [
"/usr/bin/sh", "-c",
"while [ ! -e \"$1\" ]; do sleep 0.05; done; "
"shift; exec \"$@\"",
"chv-cell-gate"])
self.assertEqual(wrapped[4],
"/run/chv/.cell-gate-chv-cell-00")
self.assertEqual(wrapped[5:],
["python3", "/app/host.py", "status"])
# 绝对路径:volatile 单元根里 /bin 未必有,/usr 必有。
self.assertTrue(wrapped[0].startswith("/usr/bin/"))
class CellInitPidPollTest(unittest.TestCase):
"""part 4:find_cell_init_pid 带超时轮询。"""
def _proc_root_with_child(self, tmp, pid=777, child=778):
task_dir = os.path.join(tmp, str(pid), "task", str(pid))
os.makedirs(task_dir)
with open(os.path.join(task_dir, "children"), "w") as fh:
fh.write(str(child))
def test_single_shot_default_unchanged(self):
with tempfile.TemporaryDirectory() as tmp:
self._proc_root_with_child(tmp)
self.assertEqual(
CELL.find_cell_init_pid(777, proc_root=tmp), 778)
self.assertIsNone(
CELL.find_cell_init_pid(999, proc_root=tmp))
def test_poll_finds_late_child(self):
import threading
with tempfile.TemporaryDirectory() as tmp:
def _late():
import time as _time
_time.sleep(0.3)
self._proc_root_with_child(tmp)
threading.Thread(target=_late, daemon=True).start()
self.assertEqual(
CELL.find_cell_init_pid(777, proc_root=tmp,
timeout=5.0), 778)
def test_poll_returns_none_on_timeout(self):
import time as _time
with tempfile.TemporaryDirectory() as tmp:
start = _time.time()
self.assertIsNone(
CELL.find_cell_init_pid(999, proc_root=tmp,
timeout=0.3))
self.assertLess(_time.time() - start, 5.0)
def test_poll_stops_when_nspawn_dead(self):
import time as _time
with tempfile.TemporaryDirectory() as tmp:
start = _time.time()
self.assertIsNone(
CELL.find_cell_init_pid(999, proc_root=tmp,
timeout=10.0,
proc_alive=lambda: False))
# nspawn 已死即立刻回,不空等 10 秒。
self.assertLess(_time.time() - start, 5.0)
if __name__ == "__main__":
unittest.main()