forked from Keelrleek/Harbor
re_match_program: one whole-program build per worktree at a time (a lock file); concurrent runs collided
This commit is contained in:
1 parent
5211cee9c4
commit
453434c2b2
1 file changed
+46
-9
+46
-9
@@ -598,15 +598,19 @@ def match_program(config, targets=None, decomp=None):
|
|||||||
text=True, encoding="utf-8", errors="replace", timeout=timeout,
|
text=True, encoding="utf-8", errors="replace", timeout=timeout,
|
||||||
cwd=str(Path(script).parent),
|
cwd=str(Path(script).parent),
|
||||||
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0))
|
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0))
|
||||||
built = run(["build", *extra], 1800)
|
# one build per worktree at a time: two runs on the same checkout write the same build folder
|
||||||
if built.returncode != 0:
|
lock_dir = Path(config.get("debugger_temp") or tempfile.gettempdir())
|
||||||
raise HarborError("the whole-program build failed: " + (built.stdout + built.stderr).strip()[-800:])
|
lock = lock_dir / ("ltcg-" + re.sub(r"[^A-Za-z0-9]+", "_", str(decomp or "main")) + ".lock")
|
||||||
with tempfile.TemporaryDirectory(dir=config.get("debugger_temp")) as tmp:
|
with _exclusive(lock, wait_seconds=1800):
|
||||||
out = Path(tmp) / "check.json"
|
built = run(["build", *extra], 1800)
|
||||||
checked = run(["check", *extra, "--json", str(out)] + (["--only", ",".join(wanted)] if wanted else []), 900)
|
if built.returncode != 0:
|
||||||
if not out.exists():
|
raise HarborError("the whole-program build failed: " + (built.stdout + built.stderr).strip()[-800:])
|
||||||
raise HarborError("the whole-program check failed: " + (checked.stdout + checked.stderr).strip()[-800:])
|
with tempfile.TemporaryDirectory(dir=config.get("debugger_temp")) as tmp:
|
||||||
rows = json.loads(out.read_text(encoding="utf-8"))
|
out = Path(tmp) / "check.json"
|
||||||
|
checked = run(["check", *extra, "--json", str(out)] + (["--only", ",".join(wanted)] if wanted else []), 900)
|
||||||
|
if not out.exists():
|
||||||
|
raise HarborError("the whole-program check failed: " + (checked.stdout + checked.stderr).strip()[-800:])
|
||||||
|
rows = json.loads(out.read_text(encoding="utf-8"))
|
||||||
counts = {}
|
counts = {}
|
||||||
for r in rows:
|
for r in rows:
|
||||||
counts[r.get("status")] = counts.get(r.get("status"), 0) + 1
|
counts[r.get("status")] = counts.get(r.get("status"), 0) + 1
|
||||||
@@ -642,3 +646,36 @@ def behaviour_check(config, targets, decomp=None, precision=24):
|
|||||||
rows = json.loads(out.read_text(encoding="utf-8"))
|
rows = json.loads(out.read_text(encoding="utf-8"))
|
||||||
keep = ("address", "name", "verdict", "reason", "weak", "counts", "notes")
|
keep = ("address", "name", "verdict", "reason", "weak", "counts", "notes")
|
||||||
return [{k: r[k] for k in keep if k in r} for r in rows]
|
return [{k: r[k] for k in keep if k in r} for r in rows]
|
||||||
|
|
||||||
|
|
||||||
|
class _exclusive:
|
||||||
|
"""A lock file shared between processes: wait for it, hold it, remove it (stale after two hours)."""
|
||||||
|
|
||||||
|
def __init__(self, path, wait_seconds=1800):
|
||||||
|
self.path, self.wait = Path(path), wait_seconds
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
import time
|
||||||
|
deadline = time.monotonic() + self.wait
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
fd = os.open(str(self.path), os.O_CREAT | os.O_EXCL | os.O_WRONLY)
|
||||||
|
os.write(fd, str(os.getpid()).encode())
|
||||||
|
os.close(fd)
|
||||||
|
return self
|
||||||
|
except FileExistsError:
|
||||||
|
try:
|
||||||
|
if time.time() - self.path.stat().st_mtime > 7200:
|
||||||
|
self.path.unlink()
|
||||||
|
continue
|
||||||
|
except FileNotFoundError:
|
||||||
|
continue
|
||||||
|
if time.monotonic() > deadline:
|
||||||
|
raise HarborError(f"another whole-program build on this worktree is still running ({self.path.name}); try again later") from None
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
def __exit__(self, *exc):
|
||||||
|
try:
|
||||||
|
self.path.unlink()
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
Reference in new issue
Block a user