|
| 1 | +# Code Execution HTTP Service |
| 2 | + |
| 3 | +## Overview |
| 4 | +This service accepts source code and optional test/checker data over HTTP, executes the code in an isolated filesystem jail, and returns the execution result. It is designed to be fast, stateless, and container-friendly. |
| 5 | + |
| 6 | +## HTTP API |
| 7 | + |
| 8 | +### `POST /run` |
| 9 | +Execute user code. |
| 10 | + |
| 11 | +Request JSON: |
| 12 | +- `timeout` (optional string): Execution limit, e.g. `"30s"`. Defaults to 30 seconds. |
| 13 | +- `solution_text` (string): Source code to run. |
| 14 | +- `lang_slug` (string): Language identifier. Supported values: |
| 15 | + - `clojure`, `cpp`, `csharp`, `dart`, `elixir`, `golang`, `haskell`, `java`, `js`, `kotlin`, `php`, `python`, `ruby`, `rust`, `swift`, `ts`, `zig` |
| 16 | +- `asserts` (optional string): JSON test data, stored as `asserts.json`. |
| 17 | +- `checker_text` (optional string): Checker code. Required for: |
| 18 | + - `cpp`, `csharp`, `dart`, `java`, `golang`, `haskell`, `kotlin`, `rust`, `swift`, `zig` |
| 19 | + |
| 20 | +Response JSON: |
| 21 | +- `exit_code` (integer or null): Process exit code, if available. |
| 22 | +- `stdout` (string): Captured standard output. |
| 23 | +- `stderr` (string): Captured standard error. |
| 24 | + |
| 25 | +### `GET /health` |
| 26 | +Returns HTTP 200 when the service is ready. |
| 27 | + |
| 28 | +## Execution Flow |
| 29 | +1. Validate request parameters. |
| 30 | +2. Create a temporary filesystem jail using an overlay of the current root. |
| 31 | +3. Write input files into a language-specific working directory: |
| 32 | + - `solution_text` → language-specific filename (e.g. `solution.py`, `Solution.java`). |
| 33 | + - `checker_text` (if provided) → language-specific checker file. |
| 34 | + - `asserts` (if provided) → `asserts.json`. |
| 35 | +4. Execute `make test` inside the jail. |
| 36 | +5. Enforce timeout; on expiration, terminate the process group. |
| 37 | +6. Capture `stdout` and `stderr` and return them with the exit code. |
| 38 | + |
| 39 | +## Files and Layout Expectations |
| 40 | +The service runs `make test` in its working directory. That directory is expected to contain language-specific runner logic. The service writes files into a subdirectory: |
| 41 | +- `check/` for most languages |
| 42 | +- `lib/` for Dart |
| 43 | + |
| 44 | +## Language File Rules |
| 45 | +For each request, the service writes the solution and (if required) checker files into the language directory (`check/` or `lib/`). It then runs `make test`, which is responsible for compiling/executing the solution and checker for that language. |
| 46 | + |
| 47 | +Filename mapping and checker requirement: |
| 48 | +- `clojure`: `solution.clj` (no checker) |
| 49 | +- `cpp`: `solution.cpp` + `checker.cpp` (checker required) |
| 50 | +- `csharp`: `Solution.cs` + `Checker.cs` (checker required) |
| 51 | +- `dart`: `solution.dart` + `checker.dart` (checker required) |
| 52 | +- `elixir`: `solution.exs` (no checker) |
| 53 | +- `golang`: `solution.go` + `checker.go` (checker required) |
| 54 | +- `haskell`: `Solution.hs` + `Checker.hs` (checker required) |
| 55 | +- `java`: `Solution.java` + `Checker.java` (checker required) |
| 56 | +- `js`: `solution.js` (no checker) |
| 57 | +- `kotlin`: `solution.kt` + `checker.kt` (checker required) |
| 58 | +- `php`: `solution.php` (no checker) |
| 59 | +- `python`: `solution.py` (no checker) |
| 60 | +- `ruby`: `solution.rb` (no checker) |
| 61 | +- `rust`: `solution.rs` + `checker.rs` (checker required) |
| 62 | +- `swift`: `solution.swift` + `checker.swift` (checker required) |
| 63 | +- `zig`: `solution.zig` + `checker.zig` (checker required) |
| 64 | +- `ts`: `solution.js` (no checker) |
| 65 | + |
| 66 | +## Isolation and Safety |
| 67 | +- The execution occurs in a chrooted directory backed by an overlay filesystem. |
| 68 | +- On Linux, it creates new namespaces (filesystem, file descriptors, mount, network) before chrooting. |
| 69 | +- The service runs commands in a separate process group for reliable termination. |
| 70 | + |
| 71 | +## Runtime Notes |
| 72 | +- If the process is PID 1 (container init), it spawns a child and acts as a signal reaper to avoid zombie processes. |
| 73 | +- The service is stateless; each request creates a fresh jail and cleans it up after execution. |
0 commit comments