Fix critical lock-expiry window found in Codex second pass
- poller.py: start lock_refresher() IMMEDIATELY after acquiring the lock, before the startup jitter and restart-storm deferral. Those sleeps can together exceed LOCK_TTL (restart defer is up to POLL_SWEEP_INTERVAL), so with the refresher started afterward the lock could expire mid-deferral and a second poller could begin sweeping concurrently — the exact hardware-storm risk this design prevents. - hwgate.py: clamp POLL_CONCURRENCY to 1 unless POLL_ALLOW_UNSAFE_CONCURRENCY is set (fragile SAS hardware; >1 can drop expanders). Warn either way. - build.sh: keep backward-compatible — a non-target first arg is treated as the commit message (./build.sh "msg" still works), known targets select web|poller|all.
This commit is contained in:
@@ -165,6 +165,13 @@ async def main() -> None:
|
||||
await asyncio.sleep(LOCK_TTL // 2)
|
||||
logger.info("poller lock acquired (%s)", TOKEN)
|
||||
|
||||
# Start the refresher IMMEDIATELY — before any pre-sweep sleep. The jitter
|
||||
# and restart-storm deferral below can together exceed LOCK_TTL, so without
|
||||
# an active refresher the lock would expire and a second poller could begin
|
||||
# sweeping concurrently (a hardware-storm risk).
|
||||
refresher = asyncio.create_task(lock_refresher())
|
||||
refresher.add_done_callback(_critical_task_done)
|
||||
|
||||
if not smartctl_available():
|
||||
logger.warning("smartctl not found — install smartmontools")
|
||||
if not sg_ses_available():
|
||||
@@ -188,8 +195,6 @@ async def main() -> None:
|
||||
logger.info("last sweep %.0fs ago — deferring first sweep %.0fs", since, wait)
|
||||
await asyncio.sleep(wait)
|
||||
|
||||
refresher = asyncio.create_task(lock_refresher())
|
||||
refresher.add_done_callback(_critical_task_done)
|
||||
leds = asyncio.create_task(led_consumer())
|
||||
try:
|
||||
while True:
|
||||
|
||||
Reference in New Issue
Block a user