Skip to content

CONCEPT Cited by 1 source

panic=unwind

Definition

panic=unwind is Rust's unwinding panic strategy: when panic!() fires (or .unwrap() on an Err, or an assertion fails), the runtime walks the stack backwards, running each frame's destructors (Drop) in reverse order of construction, until it either finds a std::panic::catch_unwind boundary or exits the thread. Contrast with concepts/panic-abort, which aborts the process immediately with no cleanup.

The unwinding strategy is:

  • The default for most native Rust targets — server, desktop, mobile.
  • Preserves state across a failed request — destructors run, locks are released, memory is freed, and the rest of the process keeps serving traffic.
  • Required for multi-tenant workloads that hold meaningful in-memory state shared across requests (e.g. Durable Objects).

panic=unwind on WebAssembly

Rust's wasm32-unknown-unknown target historically defaulted to panic=abort because Wasm had no unwinding primitive. A panic therefore trapped with the unreachable Wasm instruction and exited to the embedder with a WebAssembly.RuntimeError.

The WebAssembly Exception Handling proposal (wide engine support 2023) finally provides the primitives — try / catch / catch_all / rethrow — that a Rust unwinder needs. With RUSTFLAGS='-Cpanic=unwind' cargo build -Zbuild-std (rebuilding the standard library), Rust-on-Wasm now compiles destructor-having frames as:

try
  call <imported_func>
catch_all
  call <drop_b>
  call <drop_a>
  rethrow
end
call <drop_b>
call <drop_a>

std::panic::catch_unwind(|| some_func()) likewise compiles into a nested try / catch pair that returns Ok(value) from the normal path and Err(payload) from the catch arm, with a catch_all-guarded cannot_unwind fallback.

Effects with panic=unwind enabled on Wasm

With wasm-bindgen's support:

  • Panics in exported Rust functions are caught at the Rust↔JS boundary and surfaced as JavaScript PanicError exceptions.
  • Async exports reject the returned JS Promise with a PanicError.
  • Rust destructors run correctly on the panicking path.
  • The WebAssembly instance remains valid and reusable. One failed request does not poison subsequent requests — the concepts/sandbox-poisoning failure class is structurally contained.

What it does not address

Aborts — genuine, non-unwindable failures such as out-of-memory — cannot unwind. Those need concepts/abort-recovery instead: the embedder detects the abort via the Exception.Tag-marked recoverable exception shape vs raw abort shape, runs a set_on_abort hook, and reinitialises the instance.

Closures that capture references whose invariants depend on no-mid-request-unwind need concepts/unwind-safety machinery (MaybeUnwindSafe, Closure::new_aborting) to preserve correctness.

Seen in

Last updated · 510 distilled / 1,221 read