Treat zombie workers as terminated in tests
Why: Gitea containers may leave SIGKILLed children as zombies until PID 1 reaps them, while kill -0 still reports success. Evidence: Both timeout tests and the full AgentExecControllerTests suite pass; git diff --check passes. Impact: Changes test liveness detection only; genuinely running child processes still fail the assertions. Refs: #567
This commit is contained in:
+23
-13
@@ -41,6 +41,25 @@ def _canonical_snapshot(repo: Path) -> dict[str, str]:
|
||||
return {"head": head, "tree": tree, "status": status, "index": index}
|
||||
|
||||
|
||||
def _pid_alive(pid: int) -> bool:
|
||||
"""Return true only for a running, non-zombie process."""
|
||||
try:
|
||||
text = Path(f"/proc/{pid}/stat").read_text(
|
||||
encoding="utf-8", errors="replace"
|
||||
)
|
||||
except FileNotFoundError:
|
||||
return False
|
||||
rpar = text.rfind(")")
|
||||
if rpar != -1 and rpar + 2 < len(text) and text[rpar + 2] == "Z":
|
||||
return False
|
||||
return (
|
||||
subprocess.run(
|
||||
["kill", "-0", str(pid)], check=False, capture_output=True
|
||||
).returncode
|
||||
== 0
|
||||
)
|
||||
|
||||
|
||||
def _write_config(
|
||||
repo: Path,
|
||||
*,
|
||||
@@ -740,13 +759,8 @@ class AgentExecControllerTests(unittest.TestCase):
|
||||
self.assertNotIn("idle timeout", data["reason"])
|
||||
if child_pid_file.exists():
|
||||
child = int(child_pid_file.read_text(encoding="utf-8").strip())
|
||||
# Child must not still be alive.
|
||||
still = subprocess.run(
|
||||
["kill", "-0", str(child)],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
)
|
||||
self.assertNotEqual(still.returncode, 0)
|
||||
# A zombie is terminated even if a container PID 1 has not reaped it.
|
||||
self.assertFalse(_pid_alive(child))
|
||||
self._assert_canonical_untouched()
|
||||
|
||||
def test_idle_timeout_kills_silent_worker_before_total(self) -> None:
|
||||
@@ -821,12 +835,8 @@ class AgentExecControllerTests(unittest.TestCase):
|
||||
self.assertEqual(cleanup["reason"], "idle timeout")
|
||||
self.assertTrue(child_pid_file.is_file())
|
||||
child = int(child_pid_file.read_text(encoding="utf-8").strip())
|
||||
still = subprocess.run(
|
||||
["kill", "-0", str(child)],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
)
|
||||
self.assertNotEqual(still.returncode, 0)
|
||||
# A zombie is terminated even if a container PID 1 has not reaped it.
|
||||
self.assertFalse(_pid_alive(child))
|
||||
self._assert_canonical_untouched()
|
||||
|
||||
def test_progress_keeps_worker_alive_past_one_idle_interval(self) -> None:
|
||||
|
||||
Reference in New Issue
Block a user