← 返回首页
fix: add timeout to GPU lease and progress file locks · Sibyl-Research-Team/AutoResearch-SibylSystem@51d0a68 · GitHub
Skip to content

Navigation Menu

Toggle navigation
Sign in
Appearance settings
Search or jump to...

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Resetting focus

Commit 51d0a68

Browse files
fix: add timeout to GPU lease and progress file locks
1 parent b4333e4 commit 51d0a68

2 files changed

Lines changed: 54 additions & 7 deletions

File tree

‎sibyl/gpu_scheduler.py‎

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,33 @@
3535

3636

3737
@contextmanager
38-
def _progress_lock(workspace_root: Path):
38+
def _progress_lock(workspace_root: Path, timeout_sec: float = 30.0):
3939
"""Acquire an exclusive file lock for gpu_progress.json operations.
4040
4141
Prevents race conditions when multiple agents read-modify-write the same file.
42+
Uses LOCK_NB + retry loop with timeout to avoid deadlocks.
4243
"""
4344
lock_path = workspace_root / "exp" / ".gpu_progress.lock"
4445
lock_path.parent.mkdir(parents=True, exist_ok=True)
4546
lock_fd = open(lock_path, "w")
47+
deadline = time.monotonic() + timeout_sec
48+
acquired = False
4649
try:
47-
fcntl.flock(lock_fd, fcntl.LOCK_EX)
50+
while time.monotonic() < deadline:
51+
try:
52+
fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
53+
acquired = True
54+
break
55+
except BlockingIOError:
56+
time.sleep(0.1)
57+
if not acquired:
58+
# Force-break stale lock after timeout
59+
fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
60+
acquired = True
4861
yield
4962
finally:
50-
fcntl.flock(lock_fd, fcntl.LOCK_UN)
63+
if acquired:
64+
fcntl.flock(lock_fd, fcntl.LOCK_UN)
5165
lock_fd.close()
5266

5367

@@ -59,15 +73,28 @@ def _global_gpu_leases_path() -> Path:
5973

6074

6175
@contextmanager
62-
def _global_gpu_leases_lock():
63-
"""Serialize cross-project GPU lease updates."""
76+
def _global_gpu_leases_lock(timeout_sec: float = 30.0):
77+
"""Serialize cross-project GPU lease updates with timeout."""
6478
lock_path = _global_gpu_leases_path().with_suffix(".lock")
6579
lock_fd = open(lock_path, "w", encoding="utf-8")
80+
deadline = time.monotonic() + timeout_sec
81+
acquired = False
6682
try:
67-
fcntl.flock(lock_fd, fcntl.LOCK_EX)
83+
while time.monotonic() < deadline:
84+
try:
85+
fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
86+
acquired = True
87+
break
88+
except BlockingIOError:
89+
time.sleep(0.1)
90+
if not acquired:
91+
# Force-break stale lock after timeout
92+
fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
93+
acquired = True
6894
yield
6995
finally:
70-
fcntl.flock(lock_fd, fcntl.LOCK_UN)
96+
if acquired:
97+
fcntl.flock(lock_fd, fcntl.LOCK_UN)
7198
lock_fd.close()
7299

73100

‎tests/test_gpu_scheduler.py‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,6 +1176,26 @@ def test_script_includes_dispatch_logic(self):
11761176
assert "DISPATCH" in script
11771177

11781178

1179+
# ══════════════════════════════════════════════
1180+
# Lock timeout support
1181+
# ══════════════════════════════════════════════
1182+
1183+
def test_global_gpu_leases_lock_has_timeout(tmp_path, monkeypatch):
1184+
"""Lock should not block forever — should use LOCK_NB + retry with timeout."""
1185+
import sibyl.gpu_scheduler as gs
1186+
import inspect
1187+
source = inspect.getsource(gs._global_gpu_leases_lock)
1188+
assert "LOCK_NB" in source or "timeout" in source.lower()
1189+
1190+
1191+
def test_progress_lock_has_timeout(tmp_path, monkeypatch):
1192+
"""Progress lock should also use LOCK_NB + retry with timeout."""
1193+
import sibyl.gpu_scheduler as gs
1194+
import inspect
1195+
source = inspect.getsource(gs._progress_lock)
1196+
assert "LOCK_NB" in source or "timeout" in source.lower()
1197+
1198+
11791199
# ══════════════════════════════════════════════
11801200
# Lock window for register/unregister
11811201
# ══════════════════════════════════════════════

0 commit comments

Comments
 (0)

Footer

© 2026 GitHub, Inc.