capypad
0 day streak
rust / intermediate
Snippet

Panic Handling with std::panic::catch_unwind

catch_unwind captures panics and converts them into Result values, enabling recovery from panic states. This is essential when interfacing Rust with environments that cannot tolerate panics, such as when implementing plugins, foreign function interfaces, or async runtimes. AssertUnwindSafe is a helper for closures that the programmer guarantees are safe to unwind across.

snippet.rs
rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use std::panic::{catch_unwind, AssertUnwindSafe};
 
fn risky_operation(divisor: i32) -> i32 {
100 / divisor // Will panic if divisor is 0
}
 
fn main() {
// Successful case
let result = catch_unwind(|| {
risky_operation(10)
});
 
match result {
Ok(value) => println!("Calculation succeeded: {}", value),
Err(e) => println!("Panic occurred: {:?}", e),
}
 
// Panic case - divisor is 0
let panic_result = catch_unwind(|| {
risky_operation(0)
});
 
if panic_result.is_err() {
println!("Caught panic from division by zero!");
}
 
// Using AssertUnwindSafe for shared references
let shared_data = vec![1, 2, 3];
let safe_result = catch_unwind(AssertUnwindSafe(|| {
println!("Processing: {:?}", shared_data);
42
}));
 
println!("Safe result: {:?}", safe_result);
 
// Practical example: recoverable parsing
let numbers = vec!["10", "20", "oops", "40"];
for num_str in numbers {
let parsed = catch_unwind(|| num_str.parse::<i32>().unwrap());
match parsed {
Ok(n) => println!("Parsed: {}", n),
Err(_) => println!("Failed to parse '{}', continuing...", num_str),
}
}
}
Breakdown
1
catch_unwind(|| risky_operation(10))
Executes closure and catches any panic, returning Result<T, Box<dyn Any + Send>>
2
AssertUnwindSafe(|| ... )
Marker type asserting closure is safe to unwind through - use when you know the closure won't violate invariants
3
Ok(value) => println!("{}", value)
Normal completion - no panic occurred in the closure
4
Err(e) => println!("{:?}", e)
Panic was caught - e contains panic payload information