From 2b62a72b06e5eb8e62ad3d99008560ab0a3c108d Mon Sep 17 00:00:00 2001 From: iopapamanoglou Date: Thu, 7 Nov 2024 10:59:46 +0100 Subject: [PATCH] fix xdist --- pyproject.toml | 2 +- src/faebryk/core/cpp/__init__.py | 49 ++++++++++++++++---------------- src/faebryk/libs/util.py | 37 ++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 25 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 705e0fd9..67306643 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -100,7 +100,7 @@ cmake.source-dir = "src/faebryk/core/cpp" [tool.pytest] [tool.pytest.ini_options] # loadscope to run tests for each file in same worker -addopts = ["--import-mode=importlib", "--numprocesses=auto", "--dist=loadscope"] +addopts = ["--import-mode=importlib", "--numprocesses=auto"] filterwarnings = ["ignore:.*:DeprecationWarning"] testpaths = ["test"] diff --git a/src/faebryk/core/cpp/__init__.py b/src/faebryk/core/cpp/__init__.py index 793adfbf..40224b45 100644 --- a/src/faebryk/core/cpp/__init__.py +++ b/src/faebryk/core/cpp/__init__.py @@ -5,7 +5,7 @@ import logging from importlib.metadata import Distribution -from faebryk.libs.util import ConfigFlag, at_exit +from faebryk.libs.util import ConfigFlag, at_exit, global_lock logger = logging.getLogger(__name__) @@ -63,29 +63,30 @@ def compile_and_load(): if arch in ["arm64", "x86_64"]: other_flags += [f"-DCMAKE_OSX_ARCHITECTURES={arch}"] - run_live( - [ - "cmake", - "-S", - str(_cmake_dir), - "-B", - str(_build_dir), - "-DEDITABLE=1", - "-DPython_EXECUTABLE=" + sys.executable, - *other_flags, - ], - logger=logger, - ) - run_live( - [ - "cmake", - "--build", - str(_build_dir), - "--", - "-j", - ], - logger=logger, - ) + with global_lock(_build_dir / "lock", timeout_s=60): + run_live( + [ + "cmake", + "-S", + str(_cmake_dir), + "-B", + str(_build_dir), + "-DEDITABLE=1", + "-DPython_EXECUTABLE=" + sys.executable, + *other_flags, + ], + logger=logger, + ) + run_live( + [ + "cmake", + "--build", + str(_build_dir), + "--", + "-j", + ], + logger=logger, + ) if not _build_dir.exists(): raise RuntimeError("build directory not found") diff --git a/src/faebryk/libs/util.py b/src/faebryk/libs/util.py index ddf8ef25..ab28d08e 100644 --- a/src/faebryk/libs/util.py +++ b/src/faebryk/libs/util.py @@ -9,12 +9,14 @@ import select import subprocess import sys +import time from abc import abstractmethod from collections import defaultdict from contextlib import contextmanager from dataclasses import dataclass, fields from enum import StrEnum from itertools import chain +from pathlib import Path from textwrap import indent from typing import ( Any, @@ -33,6 +35,7 @@ get_origin, ) +import psutil from tortoise import Model from tortoise.queryset import QuerySet @@ -1174,3 +1177,37 @@ def run_live( ) return "\n".join(stdout), process + + +@contextmanager +def global_lock(lock_file_path: Path, timeout_s: float | None = None): + # TODO consider using filelock instead + + lock_file_path.parent.mkdir(parents=True, exist_ok=True) + + start_time = time.time() + while try_or( + lambda: bool(lock_file_path.touch(exist_ok=False)), + default=True, + catch=FileExistsError, + ): + # check if pid still alive + try: + pid = int(lock_file_path.read_text()) + except ValueError: + lock_file_path.unlink() + continue + assert pid != os.getpid() + if not psutil.pid_exists(pid): + lock_file_path.unlink() + continue + if timeout_s and time.time() - start_time > timeout_s: + raise TimeoutError() + time.sleep(0.1) + + # write our pid to the lock file + lock_file_path.write_text(str(os.getpid())) + try: + yield + finally: + lock_file_path.unlink()