mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-10-27 13:40:37 +00:00
* fix(lark): retry the Windows install lock instead of failing after ~10s msvcrt.LK_LOCK gives up after roughly ten seconds and surfaces contention as Permission denied, while a real install (download + setup of the lark/sandbox CLI) can hold the lock far longer. Retry the non-blocking acquisition on the Windows fallback branch so concurrent Gateway workers serialize instead of failing, mirroring the extensions manager's lock introduced in #6020. The POSIX flock branch is unchanged. Closes #6879 * test(lark): inject msvcrt stub with raising=False for Linux runners The regression test patches the module-level ``msvcrt`` attribute, which only exists on Windows (the POSIX branch imports ``fcntl`` instead), so ``monkeypatch.setattr`` with the default ``raising=True`` raised AttributeError on Linux CI (backend-unit-tests shard 4). Pass ``raising=False`` so the stub is injected on POSIX runners: ``fcntl`` is patched to ``None`` first, and ``_exclusive_install_lock`` then takes the Windows fallback branch against the fake. Windows behavior is unchanged. Scope: backend/tests/test_lark_cli_install_lock.py, 1 line. Verification: pytest tests/test_lark_cli_install_lock.py on Windows (Python 3.12, pytest 9.0.3) -- 3 passed incl. the real-contention case; Linux CI rerun is the authoritative check. * fix(lark): harden and share advisory lock retries --------- Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
45 lines
1.5 KiB
Python
45 lines
1.5 KiB
Python
"""Contention-only retries for non-blocking advisory file locks."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import errno
|
|
import time
|
|
from collections.abc import Callable
|
|
|
|
LOCK_RETRY_INTERVAL_SECONDS = 0.2
|
|
|
|
|
|
def retry_until_locked(
|
|
acquire: Callable[[], None],
|
|
*,
|
|
interval: float = LOCK_RETRY_INTERVAL_SECONDS,
|
|
deadline: float | None = None,
|
|
sleep: Callable[[float], None] = time.sleep,
|
|
monotonic: Callable[[], float] = time.monotonic,
|
|
check: Callable[[], None] | None = None,
|
|
timeout_message: str = "File lock acquisition timed out",
|
|
) -> None:
|
|
"""Retry only contention, optionally bounded by an absolute monotonic deadline.
|
|
|
|
Windows' blocking ``msvcrt.LK_LOCK`` gives up after about ten seconds.
|
|
Callers instead acquire with ``LK_NBLCK`` and choose their own deadline;
|
|
omitting it preserves an indefinite wait. Sleep/clock injection keeps
|
|
tests local rather than replacing functions on the shared time module.
|
|
"""
|
|
while True:
|
|
if check is not None:
|
|
check()
|
|
try:
|
|
acquire()
|
|
return
|
|
except OSError as error:
|
|
if error.errno not in (errno.EACCES, errno.EAGAIN, errno.EDEADLK):
|
|
raise
|
|
delay = interval
|
|
if deadline is not None:
|
|
remaining = deadline - monotonic()
|
|
if remaining <= 0:
|
|
raise TimeoutError(timeout_message) from None
|
|
delay = min(delay, remaining)
|
|
sleep(delay)
|