Appearance
Add limits and cancellation
There are three separate boundaries:
RuntimeConfigcontrols compilation and runtime-wide resource ceilings.Policychecks one module when an instance is created.context.Contextcontrols how long instantiation and calls may continue.
Run with explicit boundaries
Use the fib.wasm from Run WebAssembly from Go. Replace main.go with:
go
package main
import (
"context"
"fmt"
"log"
"os"
"time"
"github.com/wago-org/wago"
)
func run() error {
wasm, err := os.ReadFile("fib.wasm")
if err != nil {
return err
}
config := wago.NewRuntimeConfig().
WithMaxModuleBytes(16<<20).
WithMemoryLimitPages(256).
WithMaxFunctionLocals(4096).
WithInstanceLimits(8, 0)
if err := config.Validate(); err != nil {
return err
}
runtime := wago.NewRuntime(wago.WithRuntimeConfig(config))
defer runtime.Close()
module, err := runtime.Compile(wasm)
if err != nil {
return err
}
defer module.Close()
policy := wago.Policy{
MaxMemories: 1,
MaxTableEntries: 1024,
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
instance, err := runtime.Instantiate(ctx, module, wago.WithPolicy(policy))
if err != nil {
return err
}
defer instance.Close()
results, err := instance.InvokeValues(ctx, "fib", wago.ValueI32(20))
if err != nil {
return err
}
fmt.Println(results[0].I32())
return nil
}
func main() {
if err := run(); err != nil {
log.Fatal(err)
}
}sh
go run .text
6765WithMaxModuleBytes rejects oversized input before compilation. WithMemoryLimitPages caps the live size of each linear memory. WithInstanceLimits bounds simultaneously live direct instances; a closed instance returns its admission budget.
Policy is an admission check against the module's declared capabilities and limits. The zero policy is permissive. A non-empty AllowedCapabilities list is exclusive, and DeniedCapabilities always wins. A MaxMemoryBytes policy also requires the module to declare a finite maximum.
Handle cancellation and failures
Call returns context.Canceled or context.DeadlineExceeded when its context interrupts guest execution:
go
if errors.Is(err, context.DeadlineExceeded) {
return fmt.Errorf("guest exceeded its deadline: %w", err)
}Policy failures wrap wago.ErrPermissionDenied. Runtime traps can be inspected without matching error text:
go
var trap *wago.TrapError
if errors.As(err, &trap) {
log.Printf("guest trapped: %s", trap.Code)
}A context can interrupt Wasm execution, but it cannot forcibly make arbitrary Go code return. Host functions that may block should accept a bounded dependency or cooperate with cancellation. Truly hostile blocking code needs process isolation.
