Skip to main content

Crate setback

Crate setback 

Source
Expand description

§setback: setjmp/longjmp failure recovery, confined to C

protect runs a closure and returns Ok(value) on normal completion, or Err(RecoveryError) if a longjmp - triggered by a stack-overflow fault handler, an out-of-memory handler, or explicit user code via recover - abandons the closure’s stack. Everything on the abandoned stack is leaked: no Drop runs. See protect for the full safety contract.

§How it works

All setjmp/longjmp lives in a tiny C file (setback.c): rustc does not support setjmp/longjmp, so calling setjmp from Rust risks miscompilation. Rust hands C a data pointer and an extern "C" trampoline, C arms the mark and calls the trampoline, which runs the closure. A longjmp resets the stack pointer to that setjmp, jumping over every live Rust frame above it - the trampoline, the closure, and its whole call tree - and abandons them where they sit. The jump stops at the C frame, and protect returns Err(RecoveryError).

An uncaught panic crossing the extern "C" trampoline aborts (Rust 1.81+) rather than entering C.

§One global registry, keyed by thread id

The crate owns a single static intrusive doubly-linked list of active marks. Each protect call links one node, tagged with the caller’s ThreadId, and unlinks it on exit. One shared fault handler, given the faulting thread’s id, calls recover to find that thread’s innermost active mark and jump into it, or can_recover to ask whether such a mark exists without jumping. The link/unlink runs inside a critical_section, the protected closure runs outside it. You supply the critical-section impl in the final binary.

Structs§

AssertUnwindSafe
Wrap a capture (or a whole closure) to assert it is unwind-safe if needed, satisfying the UnwindSafe bound on protect. Safe in itself, you should still fulfill the safety contract of protect when the closure runs. A simple wrapper around a type to assert that it is unwind safe.
RecoveryError
Returned by protect when the closure’s stack was abandoned by a longjmp.
RecoveryFailure
Returned by recover when the given tid has no active protect scope.

Constants§

RECOVERY_GAP_BYTES
Bytes of stack that protect reserves below the recovery mark before it runs the closure - the gap a fault handler may rely on when choosing where to run recover. See the “Recovery-stack guarantee” on protect.

Functions§

can_recover
Whether recover would find a scope: true when tid has an active protect scope that accepts cause.
protect
Run f under recovery protection, tagging this scope with tid. Catches any cause; see protect_cause to recover from a single cause only.
protect_cause
Like protect, but only recovers when recover’s cause equals cause; any other cause skips this scope. See protect for the full contract.
recover
From the shared fault/OOM handler: recover the thread identified by tid by jumping into its innermost active scope that accepts cause, reporting it. protect scopes accept any cause; protect_cause scopes accept one.

Type Aliases§

ThreadId
Identifier the caller uses to tag a protect scope and that the fault handler uses to find it again. Cast your RTOS task handle / index to usize.