Spaces:
Running
Running
| from __future__ import annotations | |
| import os | |
| import platform | |
| import shutil | |
| import subprocess | |
| import sys | |
| import tempfile | |
| import time | |
| from pathlib import Path | |
| from typing import Any | |
| TIMEOUT_SECONDS = 1.0 | |
| MEMORY_LIMIT_MB = 512 | |
| OUTPUT_LIMIT_BYTES = 256 * 1024 | |
| def _sandbox_env(tmpdir: Path) -> dict[str, str]: | |
| # Run user code with a tightly scoped environment to reduce hidden state. | |
| return { | |
| "PYTHONIOENCODING": "utf-8", | |
| "PYTHONUNBUFFERED": "1", | |
| "PYTHONNOUSERSITE": "1", | |
| "HOME": str(tmpdir), | |
| "TMPDIR": str(tmpdir), | |
| "TEMP": str(tmpdir), | |
| "TMP": str(tmpdir), | |
| } | |
| def _linux_preexec_fn(timeout_seconds: float) -> Any: | |
| if platform.system().lower() != "linux": | |
| return None | |
| def _apply_limits() -> None: | |
| import resource | |
| memory_limit = MEMORY_LIMIT_MB * 1024 * 1024 | |
| cpu_limit = max(1, int(timeout_seconds) + 1) | |
| file_limit = OUTPUT_LIMIT_BYTES | |
| resource.setrlimit(resource.RLIMIT_AS, (memory_limit, memory_limit)) | |
| resource.setrlimit(resource.RLIMIT_CPU, (cpu_limit, cpu_limit)) | |
| resource.setrlimit(resource.RLIMIT_FSIZE, (file_limit, file_limit)) | |
| resource.setrlimit(resource.RLIMIT_NOFILE, (32, 32)) | |
| return _apply_limits | |
| def run_code(code: str, input_data: str, timeout_seconds: int | float | None = None) -> dict[str, Any]: | |
| timeout_value = float(TIMEOUT_SECONDS if timeout_seconds is None else timeout_seconds) | |
| temp_parent = Path(os.getenv("ADAPT_TMP_DIR", ".adapt_tmp")).resolve() | |
| temp_parent.mkdir(parents=True, exist_ok=True) | |
| tmpdir_path = Path(tempfile.mkdtemp(prefix="run_", dir=str(temp_parent))) | |
| submission_path = tmpdir_path / "submission.py" | |
| submission_path.write_text(code, encoding="utf-8") | |
| started = time.perf_counter() | |
| try: | |
| try: | |
| result = subprocess.run( | |
| [sys.executable, "-I", "-S", str(submission_path)], | |
| input=input_data, | |
| text=True, | |
| capture_output=True, | |
| timeout=timeout_value, | |
| cwd=str(tmpdir_path), | |
| env=_sandbox_env(tmpdir_path), | |
| preexec_fn=_linux_preexec_fn(timeout_value), | |
| ) | |
| except subprocess.TimeoutExpired as exc: | |
| duration_ms = round((time.perf_counter() - started) * 1000, 2) | |
| return { | |
| "stdout": str(exc.stdout or ""), | |
| "stderr": "Execution timed out", | |
| "exit_code": -1, | |
| "timed_out": True, | |
| "duration_ms": duration_ms, | |
| "sandboxed": True, | |
| "sandbox_mode": "linux_limited" if platform.system().lower() == "linux" else "portable", | |
| } | |
| duration_ms = round((time.perf_counter() - started) * 1000, 2) | |
| stdout = result.stdout[:OUTPUT_LIMIT_BYTES] | |
| stderr = result.stderr[:OUTPUT_LIMIT_BYTES] | |
| return { | |
| "stdout": stdout, | |
| "stderr": stderr, | |
| "exit_code": int(result.returncode), | |
| "timed_out": False, | |
| "duration_ms": duration_ms, | |
| "sandboxed": True, | |
| "sandbox_mode": "linux_limited" if platform.system().lower() == "linux" else "portable", | |
| } | |
| finally: | |
| shutil.rmtree(tmpdir_path, ignore_errors=True) | |