catch_unwind doesn't catch non-C++ exceptions on wasm
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
I tried this code:
#[unsafe(no_mangle)]
pub fn square(num: i32) -> std::thread::Result<i32> {
std::panic::catch_unwind(|| bar())
}
unsafe extern "C-unwind" {
safe fn bar() -> i32;
}
compiled with -Cpanic=unwind --crate-type cdylib --target wasm32-wasip1 + -Zbuild-std.
I expected to see this happen: An exception originating from bar which doesn't conform with the wasm C++ exception ABI will cause an abort, just like foreign exceptions would on native platforms when unwinding through catch_unwind.
Instead, this happened: catch_unwind only generates a wasm catch instruction matching the C++ exception tag. For unwinding out of functions that are not allowed to unwind at all we do correctly generate a catch_all instruction to call panic_cannot_unwind.
(func $square (;2;) (type 0) (param i32 i32)
(local i32 i32 i32)
global.get $__stack_pointer
i32.const 16
i32.sub
local.tee 2
global.set $__stack_pointer
block ;; label = @1
try ;; label = @2
call $bar
local.set 3
catch 0
local.set 3
local.get 2
global.set $__stack_pointer
try ;; label = @3
local.get 2
i32.const 8
i32.add
local.get 3
call $_ZN3std9panicking12catch_unwind7cleanup17h1c165d98d6186f41E
catch_all
local.get 2
global.set $__stack_pointer
call $_ZN4core9panicking19panic_cannot_unwind17h45f1d8e8d54a6393E
unreachable
end
local.get 2
i32.load offset=12
local.set 3
local.get 2
i32.load offset=8
local.set 4
local.get 0
local.get 4
i32.store
local.get 0
local.get 3
i32.store offset=4
br 1 (;@1;)
end
local.get 0
i32.const 0
i32.store
local.get 0
local.get 3
i32.store offset=4
end
local.get 2
i32.const 16
i32.add
global.set $__stack_pointer
)
Meta
rustc --version --verbose:
rustc 1.92.0-nightly (695857bc3 2025-10-21)
binary: rustc
commit-hash: 695857bc3f72ec4f59c79f323460fe488c38a53f
commit-date: 2025-10-21
host: x86_64-unknown-linux-gnu
release: 1.92.0-nightly
LLVM version: 21.1.3
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the example with rustc nightly, -Cpanic=unwind, --crate-type cdylib, target wasm32-wasip1, and -Zbuild-std, then inspect the generated WebAssembly around catch_unwind and the shown catch instructions. Done means non-C++ exceptions from bar no longer pass through catch_unwind and instead follow the expected abort behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, wasm
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100