Fix Windows backend test compatibility (#1384)

* Fix Windows backend test compatibility

* Preserve ACP path style on Windows

* Fix installer import ordering

* Address review comments for Windows fixes

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
This commit is contained in:
Admire
2026-03-26 17:39:16 +08:00
committed by GitHub
parent b3d3287b80
commit b9583f7204
10 changed files with 141 additions and 27 deletions

View File

@@ -11,7 +11,6 @@ The provider itself handles:
"""
import atexit
import fcntl
import hashlib
import logging
import os
@@ -20,6 +19,12 @@ import threading
import time
import uuid
try:
import fcntl
except ImportError: # pragma: no cover - Windows fallback
fcntl = None # type: ignore[assignment]
import msvcrt
from deerflow.config import get_app_config
from deerflow.config.paths import VIRTUAL_PATH_PREFIX, Paths, get_paths
from deerflow.sandbox.sandbox import Sandbox
@@ -42,6 +47,24 @@ DEFAULT_REPLICAS = 3 # Maximum concurrent sandbox containers
IDLE_CHECK_INTERVAL = 60 # Check every 60 seconds
def _lock_file_exclusive(lock_file) -> None:
if fcntl is not None:
fcntl.flock(lock_file, fcntl.LOCK_EX)
return
lock_file.seek(0)
msvcrt.locking(lock_file.fileno(), msvcrt.LK_LOCK, 1)
def _unlock_file(lock_file) -> None:
if fcntl is not None:
fcntl.flock(lock_file, fcntl.LOCK_UN)
return
lock_file.seek(0)
msvcrt.locking(lock_file.fileno(), msvcrt.LK_UNLCK, 1)
class AioSandboxProvider(SandboxProvider):
"""Sandbox provider that manages containers running the AIO sandbox.
@@ -405,8 +428,10 @@ class AioSandboxProvider(SandboxProvider):
lock_path = paths.thread_dir(thread_id) / f"{sandbox_id}.lock"
with open(lock_path, "a", encoding="utf-8") as lock_file:
locked = False
try:
fcntl.flock(lock_file, fcntl.LOCK_EX)
_lock_file_exclusive(lock_file)
locked = True
# Re-check in-process caches under the file lock in case another
# thread in this process won the race while we were waiting.
with self._lock:
@@ -440,7 +465,8 @@ class AioSandboxProvider(SandboxProvider):
return self._create_sandbox(thread_id, sandbox_id)
finally:
fcntl.flock(lock_file, fcntl.LOCK_UN)
if locked:
_unlock_file(lock_file)
def _evict_oldest_warm(self) -> str | None:
"""Destroy the oldest container in the warm pool to free capacity.