This commit is contained in:
root
2026-06-15 21:42:50 +00:00
parent 34a97e2577
commit 99cd92fb4a
126 changed files with 1615 additions and 1057 deletions
+2
View File
@@ -193,6 +193,7 @@ MAX_MEMORY=16777216
SESSION_TIME=2592000
HTTP_PORT=8080
WS_BROKER_OUTBOUND_TIMEOUT_SECONDS=30
```
Important settings:
@@ -204,6 +205,7 @@ Important settings:
- `BIN_DIRECTORY` stores generated C++, wasm artifacts, compile output, and runtime caches.
- `TMP_UPLOAD_PATH` and `SESSION_PATH` must be writable by the runtime.
- `HTTP_PORT` is the built-in HTTP/WebSocket listener used for WebSocket upgrade traffic and direct local probes. Bind/firewall it for local access only; nginx/Apache should be the public entry point.
- `WS_BROKER_OUTBOUND_TIMEOUT_SECONDS` controls how long a forwarded WS message can remain queued in the broker before being dropped (default `30`). Set to `0` to disable the timeout.
- `WASM_COMPILE_SCRIPT` must point to `scripts/compile_wasm_unit` unless you provide an equivalent compiler. Relative paths are resolved from the runtime root/`COMPILER_SYS_PATH`. That script calls `scripts/check_unit_wasm.py` after linking each unit and uses the pinned WASI SDK on every deployment host.
- `WASM_CORE_PATH` must point at the built `core.wasm` file.
+34 -7
View File
@@ -85,6 +85,14 @@ the boundary).
See [`docs/wasm-phase1-dvalue-abi.md`](wasm-phase1-dvalue-abi.md) for the wire
format details.
Decoder robustness note: UCEB input is untrusted across the wasm membrane. The
UCEB decoder must reject malformed magic/version/varint/length/trailing-data
inputs and excessive nesting with explicit errors, not native or wasm traps. Its
current hard nesting cap is intentionally low (64 levels) to stay well below the
guest stack limit. JSON decoding follows the same rule for malformed strings and
unicode escapes: validate bounds before every read and return an empty/partial
`DValue` rather than reading beyond the input.
---
## 3. Units, handlers, and export naming
@@ -144,6 +152,19 @@ suspend the native SIGSEGV/SIGILL recovery handler around the wasm call so that
Wasmtime's own trap signals are not escalated into a native fatal signal (see
`serve_via_wasm` in `handle_complete`).
### Task callbacks and workspace lifetime
`task()` and `task_repeat()` are fork-backed. The `uce_host_task_spawn` hostcall
captures the current `WasmWorkspace*`, but `src/lib/sys.cpp::task()` invokes the
captured callback only in the forked child, before the hostcall stack unwinds in
that child. The parent request may return and destroy its workspace; the child
still has its own copy-on-write stack and its own copy of the per-request wasm
workspace. This means a delayed task callback can run after the spawning request
returns without dereferencing the parent's destroyed workspace. It is still a
callback into the inherited child workspace, not a fresh normal request
workspace; avoid adding host resources to `WasmWorkspace` that are invalid across
`fork()` unless task callback handling is changed to birth a fresh workspace.
---
## 5. Request dispatch (`handle_complete`)
@@ -198,12 +219,14 @@ broker loop:
a non-empty STDIN makes the FastCGI transport flush a premature response
before `on_complete` ever runs.
3. Connect to `/run/uce.sock` (non-blocking) and queue the encoded request in
`ws_broker_outbound[fd]`.
`ws_broker_outbound[fd]` with an enqueue timestamp.
`ws_broker_drain_outbound()` runs after every `process(50)` tick: it finishes
writing each queued request, then drains and discards the reply (the unit's
output comes back via the command socket, not this reply), closing the fd when
the worker closes its end.
the worker closes its end. If a forward remains pending beyond
`WS_BROKER_OUTBOUND_TIMEOUT_SECONDS` (default `30`), the broker drops and
closes it so a wedged worker cannot pin broker fds/memory indefinitely.
### 6.2 Outbound: `ws_*` commands flushed back to the broker
@@ -211,8 +234,10 @@ Any unit code — not just WebSocket handlers — may call `ws_send` / `ws_send_
/ `ws_close`. In the workspace these **record dispatch commands** rather than
touching a socket (the workspace owns no connections); `wasm-core`'s `ws_*`
(`src/lib/sys.cpp`) append to `websocket_dispatch_commands`, and
`finish_response_meta` (`src/wasm/core.cpp`) emits them as `ws_commands` (plus
`ws_connection_state` if the handler mutated per-connection state).
`finish_response_meta` (`src/wasm/core.cpp`) emits them as `ws_commands`.
If the handler changed per-connection state, the core also emits
`ws_connection_state` even when no commands were emitted, and the native
backend flushes this state-only batch to the broker.
`wasm_backend_serve` (`src/wasm/backend.cpp`) flushes that batch at workspace
teardown — in **any** scenario, not just WS handlers — to the broker's command
@@ -239,9 +264,10 @@ serve_http dispatcher uses, so there is no duplicated request-forwarding code.
handlers (it renders nothing, so it accepts every request straight through to
`on_complete`), wires `on_complete=ws_broker_complete` and
`on_websocket_message=ws_broker_ws_message`, listens on `HTTP_PORT` and the
command socket, and loops `process(50)` + `drain_outbound()`. The design is
**non-blocking outbound dispatch + async command-socket flush, all in the
broker's single epoll loop** — the broker never blocks on a worker.
command socket, and loops `process(50)` + `drain_outbound(timeout)`. The
`timeout` comes from `WS_BROKER_OUTBOUND_TIMEOUT_SECONDS` (default `30`). The
design is **non-blocking outbound dispatch + async command-socket flush, all in
the broker's single epoll loop** — the broker never blocks on a worker.
The parent respawns the broker if it dies (`ws_broker_alive` / `ensure_ws_broker`
in `main()`).
@@ -288,6 +314,7 @@ header free-functions are `inline`. The wasm backend exposes only declarations
| `CLI_SOCKET_PATH` | `/run/uce/cli.sock` | Worker CLI socket. |
| `HTTP_PORT` | `8080` | Raw HTTP + WebSocket port — owned by the WS broker. |
| `WS_BROKER_SOCKET_PATH` | `/run/uce/ws-broker.sock` | Broker command socket for `ws_*` flushes. |
| `WS_BROKER_OUTBOUND_TIMEOUT_SECONDS` | `30` | Max lifetime in seconds for queued WS broker forwards before drop. |
| `WORKER_COUNT` | `4` | Number of uniform worker processes. |
---