Making Rust Workers reliable: panic and abort recovery in wasm‑bindgen
Summary
Recent updates to wasm-bindgen and the Rust Workers runtime introduce mechanisms to recover from Rust panics and WebAssembly aborts. These improvements prevent a single failed request from poisoning the WebAssembly instance, which previously could have caused subsequent or concurrent requests to fail.
Key Points
- Implemented
panic=unwindsupport for thewasm32-unknown-unknowntarget using the WebAssembly Exception Handling proposal. - Introduced
PanicErrorexceptions in JavaScript, allowing Rust panics to be caught and handled at the JS-Rust boundary. - Added
set_on_abortto allow developers to attach custom recovery handlers during initialization. - Added
Closure::new_abortingtowasm-bindgento safely handle closures where unwind safety cannot be guaranteed. - Introduced an experimental
--reset-state-functionflag forwasm-bindgento allow Wasm libraries to support automatic state reinitialization. - Utilized
extern "C-unwind"for exports to explicitly allow unwinding across the FFI boundary.
Technical Details
To enable panic unwinding, developers must compile using RUSTFLAGS='-Cpanic=unwind' cargo build -Zbuild-std. This configuration rebuilds the standard library with unwind support, allowing the WebAssembly runtime to utilize try/catch and catch_all instructions. This ensures that Rust destructors (Drop) are correctly executed even if an imported function panics. To distinguish between recoverable foreign exceptions and unrecoverable aborts (such as Out-of-Memory errors), the implementation leverages Exception.Tag from the WebAssembly Exception Handling specification.
At the JavaScript boundary, wasm-bindgen now catches panics in exported functions and surfaces them as PanicError exceptions. For asynchronous exports, a panic results in the rejection of the returned JavaScript Promise with a PanicError. For Wasm libraries used in JavaScript environments, the --reset-state-function flag allows the Rust application to expose a function that the JavaScript host can call to reset the internal Wasm instance state without needing to re-import or recreate the module.
Impact / Why It Matters
These changes eliminate "instance poisoning," ensuring that a single failed request or an unexpected abort does not cascade into failures for other concurrent or subsequent requests within the same Worker instance.