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 52d5ae20..ce26b6b5 100644 --- a/dokimi/dokimi/harnesses/docker_solver.py +++ b/dokimi/dokimi/harnesses/docker_solver.py @@ -205,7 +205,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_run_container_name.py b/dokimi/tests/test_run_container_name.py new file mode 100644 index 00000000..d04129f8 --- /dev/null +++ b/dokimi/tests/test_run_container_name.py @@ -0,0 +1,30 @@ +# 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) + (name,) = {a[a.index("--name") + 1] for a in cli.args if a[0] == "run"} + # every `docker rm -f` of this arm must name this arm's container + assert {a[-1] for a in cli.args if a[0] == "rm"} == {name} + names.add(name) + assert len(names) == 2 and all(n.startswith(f"dokimi-run-{task.name}-") for n in names)