simonycl's picture
Upload folder using huggingface_hub
b2ebc95 verified
Raw History Blame Contribute Delete
2.75 kB
#!/usr/bin/env python3
"""List and (with --delete) reclaim leaked prime tunnels.
Why this is needed: every eval episode opens a host tunnel so the sandbox can reach the local
vLLM server, and the account is capped at **32 concurrent tunnels**. `PrimeTunnel.expose` releases
its tunnel in a `finally` that is shielded against cancellation — so a normal exit or SIGTERM
cleans up properly. **SIGKILL does not.** Kill -9 an eval process with 24 rollouts in flight and
you leak 24 tunnels; do that a few times and all 32 slots are gone. Every subsequent episode then
dies instantly with
TunnelError: TunnelLimitReachedError: Maximum number of tunnels (32) reached
which looks like a sandbox-pool problem and is not one. It is also invisible in `/resources`.
Two rules that follow:
* Stop eval runs with SIGTERM, never `kill -9`, unless you clean up afterwards.
* Total `max_concurrent` across ALL simultaneously running eval processes must stay under 32.
Two arms at 24 each is 48 and cannot work, however healthy the pool looks.
Run with no arguments to list; `--delete` removes every tunnel the token owns, so only do that
when no eval is running.
"""
import asyncio
import sys
async def main() -> None:
from prime_tunnel import TunnelClient
delete = "--delete" in sys.argv
client = TunnelClient()
try:
result = client.list_tunnels()
if hasattr(result, "__await__"):
result = await result
items = list(getattr(result, "items", None) or getattr(result, "tunnels", None) or result)
print(f"tunnels held by this token: {len(items)} / 32")
if not delete:
print("(pass --delete to reclaim them — only when no eval run is active)")
return
ids = [getattr(t, "tunnel_id", None) or getattr(t, "id", None) for t in items]
ids = [i for i in ids if i]
if not ids:
return
try:
res = client.bulk_delete_tunnels(ids)
if hasattr(res, "__await__"):
await res
print(f"deleted {len(ids)} tunnels (bulk)")
except Exception as exc:
print(f"bulk delete failed ({exc}); falling back to one at a time")
ok = 0
for tid in ids:
try:
res = client.delete_tunnel(tid)
if hasattr(res, "__await__"):
await res
ok += 1
except Exception as inner:
print(f" {tid}: {inner}")
print(f"deleted {ok}/{len(ids)} tunnels")
finally:
close = client.close()
if hasattr(close, "__await__"):
await close
if __name__ == "__main__":
asyncio.run(main())