mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/usestrix/strix.git
synced 2026-09-20 08:03:42 +08:00
fix(runtime): tear the sandbox down when staging is cancelled
CancelledError is not an Exception, so a run cancelled during the extra-file upload or unpack left a created-but-uncached sandbox running.
This commit is contained in:
@@ -334,7 +334,7 @@ async def create_or_reuse(
|
||||
report("Placing workspace files")
|
||||
try:
|
||||
await stage_extra_files(session, extra_file_archive)
|
||||
except Exception:
|
||||
except BaseException:
|
||||
await _discard_session(client, session)
|
||||
raise
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import io
|
||||
import tarfile
|
||||
from dataclasses import dataclass
|
||||
@@ -479,6 +480,46 @@ async def test_a_failed_unpack_tears_the_session_down(monkeypatch: pytest.Monkey
|
||||
assert scan_id not in session_manager._SESSION_CACHE
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_a_cancelled_unpack_tears_the_session_down(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
"""A run cancelled mid-staging must not leave the sandbox running."""
|
||||
|
||||
class _HangingSession(_Session):
|
||||
async def exec(self, *argv: str, timeout: float | None = None) -> _ExecResult:
|
||||
del argv, timeout
|
||||
await asyncio.Event().wait()
|
||||
raise AssertionError("unreachable")
|
||||
|
||||
fake_session = _HangingSession()
|
||||
fake_client = _Client()
|
||||
|
||||
async def _backend(**_kwargs: Any) -> tuple[Any, Any]:
|
||||
return fake_client, fake_session
|
||||
|
||||
scan_id = "unpack-cancelled"
|
||||
backend_name = f"test-{scan_id}"
|
||||
_use_backend(monkeypatch, backend_name, _backend, supports_bind_mounts=True)
|
||||
try:
|
||||
task = asyncio.create_task(
|
||||
session_manager.create_or_reuse(
|
||||
scan_id,
|
||||
image="img",
|
||||
local_sources=[],
|
||||
extra_files=[{"workspace_path": "/workspace/notes.md", "content": b"x"}],
|
||||
)
|
||||
)
|
||||
while not fake_session.writes:
|
||||
await asyncio.sleep(0)
|
||||
task.cancel()
|
||||
with pytest.raises(asyncio.CancelledError):
|
||||
await task
|
||||
finally:
|
||||
_forget_backend(backend_name)
|
||||
|
||||
assert fake_client.deleted == [fake_session]
|
||||
assert scan_id not in session_manager._SESSION_CACHE
|
||||
|
||||
|
||||
def test_only_bind_mount_capable_backends_are_registered_as_such() -> None:
|
||||
assert backend_supports_bind_mounts("docker")
|
||||
assert not backend_supports_bind_mounts("e2b")
|
||||
|
||||
Reference in New Issue
Block a user