SLEdge only implemented a subset of the WASI syscall interface
SLEdge assumes that every module it loads is a WASI module compiled by aWsm and linked against libsledge. aWsm can also emit WebAssembly outside the WASI spec (for example, modules that do not use linear memory), but such modules are not supported by SLEdge.
Concretely, a module must satisfy the following to run:
- WASI, compiled by aWsm. A module is produced by running aWsm over a
*.wasmfile to emit*.bc, then linking that*.bcwithlibsledgeinto a*.wasm.so(seeapplications/Makefile). The runtimedlopens the resulting*.soand resolves the aWsm-generatedsledge_abi__*symbols (seeruntime/include/sledge_abi_symbols.h). - Linear memory is mandatory. SLEdge's entire I/O model lives in the module's linear memory: the body of an inbound HTTP request is copied into the module's view of stdin, and stdout/stderr are read back out of linear memory to form the response (see "File System" below). A module that does not use linear memory cannot exchange data with the runtime and is rejected at load time, because its aWsm-generated memory symbols (
sledge_abi__init_mem,sledge_abi__wasm_memory_starting_pages,sledge_abi__wasm_memory_max_pages) are absent.
Note that the presence of the wasi_snapshot_preview1_* import shims is not a useful signal of WASI-ness: those symbols are provided by libsledge and are unconditionally exported from every *.so via --whole-archive --export-dynamic, regardless of which WASI calls the module actually imports. Validation therefore keys off the aWsm-generated module symbols, not the WASI import shims.
The sledge_abi__init_globals symbol is only emitted when aWsm is run with the --runtime-globals flag. SLEdge tolerates its absence (globals are then inlined as constants by aWsm), so this symbol is resolved but not required. The "correct" configuration for SLEdge has not been settled; applications/Makefile currently builds with --runtime-globals.
The WASI calls args_sizes_get and args_get are supported. HTTP query parameters are captured and passed as arguments.
The WASI calls environ_get and environ_sizes_get are supported, but mostly unused. The current behavior is to to pass the runtime's environment variables into the sandbox. This is likely undesirable.
Presumably, the runtime should provide a standard set of environment variables and also allow the JSON spec to set additional function-specific environment variables.
See the reference of environment variables generated by WAGI for details: https://github.com/deislabs/wagi/blob/main/docs/environment_variables.md
clock_time_get is implemented but untested. clock_res_get is unimplemented.
SLEdge only supports fd_read from stdin and fd_write to stderr or stdout.
stdin is populated with the body of an HTTP POST request. stdout and stderr are both written in an interleaved fashion into a buffer and sent back to the client as the response body.
Actual access to the file system is unsupported, and sandboxes are not provided any preopened descriptors.
poll_oneoff is unsupposed because SLEdge serverless functions are short lived. Sandboxed functions are assumed to make blocking reads/writes to stdin/stdout/stderr, and the serverless runtime is responsible for causing serverless functions to sleep and wake.
proc_exit is supported and causes a sandbox to terminate execution.
proc_raise is not supported. Signals are used by the runtime to provide preemption and context switching. It would be dangerous to trigger actual host signals from a sandbox.
However, the function could be implemented by creating a switch on the wasi signal and either ignoring or handling the signal within the proc_raise function itself.
SIGABRT could trigger the sandbox to exit in an abnormal condition.
The default ignore behavior could log the unexpected signal and return.
random_get is supported but largely untested.
sched_yield is unsupported. This does not match with the run-to-completion nature of serverless.
In the case of EDF, a sandbox would always yield to itself. However, in the case of FIFO, we could enable this call to allow for a worker to "round robin" within a runqueue. However, it is unclear what the rationale would be to allow a serverless function to impact the scheduler.
All socket syscalls are unimplemented because the current logic around sock_accept and sock_shutdown seems to be focused on long-lived daemon nanoprocesses that handle multiple requests. The poll_oneoff call also seems to be based on this usecase.
Generally, a serverless function is expected to only make outbound network requests. However, this use case does not seem to be currently supported by WASI.