exec the code in a separate thread and collect the stdout and stderr. If the code takes longer than timeout seconds to run, then we attempt to kill it. If it takes longer than wait_after_kill seconds to die, then we give up and return the result anyway. (The thread will die when its
(
code: str,
timeout_sec: float,
wait_after_kill=15.0,
minimum_free_ram_bytes=800_000_000,
log=False,
)
| 104 | |
| 105 | |
| 106 | async def run_python( |
| 107 | code: str, |
| 108 | timeout_sec: float, |
| 109 | wait_after_kill=15.0, |
| 110 | minimum_free_ram_bytes=800_000_000, |
| 111 | log=False, |
| 112 | ) -> str: |
| 113 | """ |
| 114 | exec the code in a separate thread and collect the stdout and stderr. |
| 115 | If the code takes longer than timeout seconds to run, then we attempt to kill it. |
| 116 | If it takes longer than wait_after_kill seconds to die, then we give up and return the result anyway. |
| 117 | (The thread will die when its running system call finishes executing.) |
| 118 | |
| 119 | Variables are shared between threads, so e.g. `shared_box[0] += 1` works. Note that `x += 1` won't work. |
| 120 | """ |
| 121 | from pyhooks import Actions # type: ignore |
| 122 | |
| 123 | await Actions().check_safety(code) |
| 124 | |
| 125 | async with aiohttp.ClientSession( |
| 126 | timeout=aiohttp.ClientTimeout( |
| 127 | total=60 * 25, sock_connect=60 * 25, sock_read=60 * 25 |
| 128 | ) |
| 129 | ) as session: |
| 130 | try: |
| 131 | async with session.post( |
| 132 | "http://localhost:9712/run_python", |
| 133 | json={ |
| 134 | "code": code, |
| 135 | "timeout": timeout_sec, |
| 136 | "wait_after_kill": wait_after_kill, |
| 137 | "minimum_free_ram_bytes": minimum_free_ram_bytes, |
| 138 | "log": log, |
| 139 | }, |
| 140 | ) as resp: |
| 141 | # encode and decode to prevent errors from unicode surrogate characters |
| 142 | return ( |
| 143 | (await resp.json())["result"] |
| 144 | .encode("utf-8", errors="replace") |
| 145 | .decode("utf-8") |
| 146 | ) |
| 147 | except Exception as e: |
| 148 | print(f"Error connecting to python server: {e}", file=sys.stderr) |
| 149 | return f"Unknown error. May be caused by python code timeout after 25 minutes. Details: {e}" |
| 150 | |
| 151 | |
| 152 | async def _run_tests(): |
no test coverage detected