From 82d8a5a00e0b4b17a5b783caaf0a39b279ef2be2 Mon Sep 17 00:00:00 2001 From: Nikolay Petrov Date: Sat, 24 Oct 2026 11:08:20 -0700 Subject: [PATCH 1/2] fix(docker): a random suffix on the run container name Two docker-* cells of the same task in one suite process got the same dokimi-run-- name; the second cell's rm -f removed the first's container. Signed-off-by: Nikolay Petrov --- .../20261024_121000_napetrov_run-container-name.md | 5 +++++ dokimi/dokimi/harnesses/docker_solver.py | 2 +- dokimi/tests/test_container_agent.py | 12 ++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 dokimi/changelog.d/20261024_121000_napetrov_run-container-name.md diff --git a/dokimi/changelog.d/20261024_121000_napetrov_run-container-name.md b/dokimi/changelog.d/20261024_121000_napetrov_run-container-name.md new file mode 100644 index 00000000..65ac3321 --- /dev/null +++ b/dokimi/changelog.d/20261024_121000_napetrov_run-container-name.md @@ -0,0 +1,5 @@ +### Fixed + +- **Two `docker-*` cells of one task in one process no longer share a + container name** — the name `dokimi-run--` gets a random suffix, + so one cell's cleanup cannot remove the other's container. diff --git a/dokimi/dokimi/harnesses/docker_solver.py b/dokimi/dokimi/harnesses/docker_solver.py index 87b36cf0..228102ca 100644 --- a/dokimi/dokimi/harnesses/docker_solver.py +++ b/dokimi/dokimi/harnesses/docker_solver.py @@ -198,7 +198,7 @@ def run( log = log_path.open("w", encoding="utf-8") usage: Optional[UsageRecord] = None image = f"dokimi/{task.name}:latest" - container = f"dokimi-run-{task.name}-{os.getpid()}" + container = f"dokimi-run-{task.name}-{os.getpid()}-{os.urandom(3).hex()}" # two cells in one process solve_timeout = timeout_sec or task.timeout_sec or _DEFAULT_SOLVE_TIMEOUT start = time.time() returncode = 0 diff --git a/dokimi/tests/test_container_agent.py b/dokimi/tests/test_container_agent.py index 6f93daed..1ccdd285 100644 --- a/dokimi/tests/test_container_agent.py +++ b/dokimi/tests/test_container_agent.py @@ -1249,3 +1249,15 @@ def test_an_announced_arm_does_not_warn_and_the_notice_is_on_by_default( assert result.metrics["skill_notice"] is True assert "demo-skill" in seen["argv"][seen["argv"].index("-p") + 1] assert "WARNING" not in (tmp_path / f"out-{name}" / "run.log").read_text(encoding="utf-8") + + +def test_two_runs_of_one_task_in_one_process_get_their_own_container(tmp_path): + # A suite runs every harness cell in one process: a pid-only name made the + # second cell's `docker rm -f` kill the first cell's container. + task = load_task(_task(tmp_path)) + names = set() + for arm in ("a", "b"): + cli = DockerCLI() + create_harness("docker-oracle", runner=cli).run(task, output_dir=tmp_path / arm) + names |= {a[a.index("--name") + 1] for a in cli.args if a[0] == "run"} + assert len(names) == 2 and all(n.startswith(f"dokimi-run-{task.name}-") for n in names) From 1459ab6a4881d3f5dad1bc9530ab83472d371ca3 Mon Sep 17 00:00:00 2001 From: Nikolay Petrov Date: Sat, 24 Oct 2026 12:06:55 -0700 Subject: [PATCH 2/2] test: move the container-name test to its own file (growth limit) Signed-off-by: Nikolay Petrov --- dokimi/tests/test_container_agent.py | 12 ----------- dokimi/tests/test_run_container_name.py | 27 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 12 deletions(-) create mode 100644 dokimi/tests/test_run_container_name.py diff --git a/dokimi/tests/test_container_agent.py b/dokimi/tests/test_container_agent.py index 1ccdd285..6f93daed 100644 --- a/dokimi/tests/test_container_agent.py +++ b/dokimi/tests/test_container_agent.py @@ -1249,15 +1249,3 @@ def test_an_announced_arm_does_not_warn_and_the_notice_is_on_by_default( assert result.metrics["skill_notice"] is True assert "demo-skill" in seen["argv"][seen["argv"].index("-p") + 1] assert "WARNING" not in (tmp_path / f"out-{name}" / "run.log").read_text(encoding="utf-8") - - -def test_two_runs_of_one_task_in_one_process_get_their_own_container(tmp_path): - # A suite runs every harness cell in one process: a pid-only name made the - # second cell's `docker rm -f` kill the first cell's container. - task = load_task(_task(tmp_path)) - names = set() - for arm in ("a", "b"): - cli = DockerCLI() - create_harness("docker-oracle", runner=cli).run(task, output_dir=tmp_path / arm) - names |= {a[a.index("--name") + 1] for a in cli.args if a[0] == "run"} - assert len(names) == 2 and all(n.startswith(f"dokimi-run-{task.name}-") for n in names) diff --git a/dokimi/tests/test_run_container_name.py b/dokimi/tests/test_run_container_name.py new file mode 100644 index 00000000..dc20b765 --- /dev/null +++ b/dokimi/tests/test_run_container_name.py @@ -0,0 +1,27 @@ +# Copyright (C) 2026 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +"""The docker-* task container's name is unique per cell, not per process.""" + +from __future__ import annotations + +from dokimi.harnesses import load_task +from dokimi.harnesses.registry import create_harness +from docker_cli_fake import DockerCLI + + +def test_two_runs_of_one_task_in_one_process_get_their_own_container(tmp_path): + # A suite runs every harness cell in one process: a pid-only name made the + # second cell's `docker rm -f` remove the first cell's container. + task_dir = tmp_path / "t" + for d in ("tests", "environment", "solution"): + (task_dir / d).mkdir(parents=True) + (task_dir / "instruction.md").write_text("x", encoding="utf-8") + (task_dir / "task.toml").write_text("[metadata]\ntags = []\n", encoding="utf-8") + task = load_task(task_dir) + names = set() + for arm in ("a", "b"): + cli = DockerCLI() + create_harness("docker-oracle", runner=cli).run(task, output_dir=tmp_path / arm) + names |= {a[a.index("--name") + 1] for a in cli.args if a[0] == "run"} + assert len(names) == 2 and all(n.startswith(f"dokimi-run-{task.name}-") for n in names)