Skip to content

Commit 800d1ea

Browse files
authored
Merge pull request #503 from Anionix/codex/bug-502-private-parent-race
Fix parallel run-parent creation race
2 parents 721d8b8 + 269afe4 commit 800d1ea

2 files changed

Lines changed: 56 additions & 2 deletions

File tree

‎src/format_bench/workflow.py‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import hashlib
44
import shutil
5+
import stat
56
from datetime import datetime, timezone
67
from pathlib import Path
78
from typing import Iterable
@@ -58,9 +59,19 @@ def _create_missing_private_parents(destination: Path) -> None:
5859

5960
# LLM contract: EXISTING_ANCESTOR -> PRIVATE_ANCESTORS_READY | FAILED.
6061
# Create shallow-to-deep without parents=True so every new level requests
61-
# 0700; any mkdir failure stops before the private run leaf is created.
62+
# 0700. A concurrent private creator is safe; every other mkdir failure
63+
# stops before the private run leaf is created.
6264
for directory in reversed(missing):
63-
directory.mkdir(mode=0o700)
65+
try:
66+
directory.mkdir(mode=0o700)
67+
except FileExistsError as error:
68+
existing_mode = directory.stat(follow_symlinks=False).st_mode
69+
if not stat.S_ISDIR(existing_mode):
70+
raise
71+
if stat.S_IMODE(existing_mode) & 0o077:
72+
raise PermissionError(
73+
f"concurrently created run ancestor is not private: {directory}"
74+
) from error
6475

6576

6677
def _safe_format_component(

‎tests/test_workflow.py‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,49 @@ def record_mode(
259259
assert (run_dir / "manifest.json").is_file()
260260

261261

262+
@pytest.mark.skipif(os.name != "posix", reason="POSIX directory-mode contract")
263+
@pytest.mark.parametrize(
264+
("raced_mode", "expected_error"),
265+
((0o700, None), (0o755, PermissionError)),
266+
)
267+
def test_missing_private_parent_validates_concurrent_creator(
268+
tmp_path: Path,
269+
monkeypatch: pytest.MonkeyPatch,
270+
raced_mode: int,
271+
expected_error: type[Exception] | None,
272+
) -> None:
273+
existing_parent = tmp_path / "existing"
274+
existing_parent.mkdir(mode=0o700)
275+
raced_parent = existing_parent / "runs"
276+
destination = raced_parent / "run"
277+
real_mkdir = Path.mkdir
278+
raced = False
279+
280+
def race_mkdir(
281+
path: Path,
282+
mode: int = 0o777,
283+
parents: bool = False,
284+
exist_ok: bool = False,
285+
) -> None:
286+
nonlocal raced
287+
if path == raced_parent and not raced:
288+
real_mkdir(path, mode=raced_mode)
289+
path.chmod(raced_mode)
290+
raced = True
291+
real_mkdir(path, mode=mode, parents=parents, exist_ok=exist_ok)
292+
293+
monkeypatch.setattr(Path, "mkdir", race_mkdir)
294+
295+
if expected_error is None:
296+
workflow._create_missing_private_parents(destination)
297+
else:
298+
with pytest.raises(expected_error, match="not private"):
299+
workflow._create_missing_private_parents(destination)
300+
301+
assert raced is True
302+
assert stat.S_IMODE(raced_parent.stat().st_mode) == raced_mode
303+
304+
262305
@pytest.mark.skipif(os.name != "posix", reason="POSIX directory-mode contract")
263306
@pytest.mark.parametrize("mask", (0o002, 0o000))
264307
def test_prepare_run_creates_missing_default_parent_privately(

0 commit comments

Comments
 (0)