If (this block of code panics) { println ... }

In Rust/wasm, is there a way to say:

run { ... this block of code }
and, if it crashes, do web_sys::console::log_1(....)

Use case, I have a function foo that is called many many times. Way too many times for me to add a println! to every call.

Once in a while, something that foo calls panics!() .. and I would love to know what the argument to foo was, when something that foo called ends up panicing.

It sounds like you are looking for catch_unwind.

2 Likes

Based on the documentation, std::panic::catch_unwind is indeed what I want.

However, it appears to be a no-op in Rust/wasm32.

I'm pretty ignorant of this topic, but here's a previous thread regarding catch_unwind on wasm.

@quinedot : Definitely informative. Thanks!

If I'm reading that github thread correctly:

  1. std::panic::catch_unwind requires panic='unwind' and does not work with panic='abort'

  2. wasm32-unknown-unknown only supports panic='abort', blocking on some wasm exception handling spec

@bjorn3: Sorry to bother you again. Since you answered in other thread. Can you please confirm of the two above statements are true / false ?

Both statements are true.

1 Like

If the only panic behavior available is abort, I think there is no way to catch it.

From the Rust side, certainly. I have no experience with WASM, but I expect the host JS environment has some way to tell if the program has halted; you could build something around that.

This isn't possible on WebAssembly at the moment.

The unwinding process in a browser and VMs like Wasmer will just pop WebAssembly stack frames with no concern for the data they contain. From memory, there is a proposal for destructors which would let you use RAII to make sure things are cleaned up during an exception, but I don't know if it's been implemented by any runtimes (browser or otherwise) yet.

Have you thought of wiring something like tracing up? You could add a #[tracing::instrument] annotation to the function (probably at the TRACE level so it doesn't spam you unnecessarily), and the last log message before the panic will tell you the function's arguments.

2 Likes
  1. Thank you everyone for your help.

  2. I ended up finding the bug in my code (by luck), but not solving the general problem (i.e. how to catch panics in wasm).

If anyone else has insights on catching panic in wasm, I am happy to listen.

Thanks!

Unfortunately, the answer is simply that it can't be done.

1 Like

Correct me if I'm wrong. The statement you are making is along the lines of "assuming no significant performance loss, there's currently no known way to do it"

I, on the other hand, am willing to suffer 10x-100x performance loss. Why? It's an annoying bug that (1) appears after a few hundred milliseconds and (2) I spent an evening chasing down. If there was some crazy config option that allowed catch_unwind in wasm but had a 10x-100x performance hit, I'd take it -- run the wasm for tens of seconds -- and bam, get the inputs to the fn I wanted.

This is not something I need in production code; only for chasing down bugs.

How about printing the argument to foo every time it is called? The last print would be the argument it received when it panics.

Unfortunately:

  1. there are 50+ webworkers running (and apparently console.log goes to same dev console)

  2. On Chrome/Linux, I have been running into this issue where after a high volume of console.logs, the dev console sometimes just ... crashes / freezes.

If the goal is simply to print something on a panic, what you want is to set the panic hook.

The panic hook gets limited information about the execution context that panicked (basically, just the stacktrace), but if you're using something like tracing and tracing-error, you can capture semantic information in the tracing spans and then print out the span trace in the panic hook to see that context.

color-eyre will even install a panic hook doing this for you (if you tell it to enable spantraces and provide a tracing subscriber with the error layer).

4 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.