capypad
0 Tage Serie
rust / intermediate
Snippet

Panik-Wiederherstellung mit catch_unwind

Die catch_unwind-Funktion ermöglicht Wiederherstellung von Panics, indem sie Closure-Ausführung kapselt und Results zurückgibt, wobei Ok das normale Ergebnis enthält oder Err die Panic-Nutzlast. AssertUnwindSafe ist ein Marker-Trait, das anzeigt, dass die Closure keine Ressourcen enthält, die deterministische Bereinigung durch Drop benötigen. Wenn eine Panic auftritt, führt Rust weiterhin Destruktoren für Drop-Typen während des Entladens aus, aber catch_unwind verhindert, dass die Panic zum aufrufenden Thread propagiert. Dies ist wertvoll zum Isolieren gefährlichen Codes in Tests oder Server-Anfragsverarbeitung.

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(input: i32) -> Result<i32, String> {
if input < 0 {
panic!("Negative input not allowed: {}", input);
}
Ok(input * 2)
}
 
fn safe_wrapper() {
let result = catch_unwind(AssertUnwindSafe(|| {
risky_operation(-5)
}));
 
match result {
Ok(Ok(value)) => println!("Success: {}", value),
Ok(Err(msg)) => println!("Logic error: {}", msg),
Err(_) => println!("Panic was caught!"),
}
}
 
struct Resource {
data: String,
}
 
impl Drop for Resource {
fn drop(&mut self) {
println!("Cleaning up: {}", self.data);
}
}
 
fn with_cleanup() {
let result = catch_unwind(AssertUnwindSafe(|| {
let resource = Resource { data: String::from("allocated") };
panic!("Simulated failure");
}));
if result.is_err() {
println!("Panic caught, destructor still ran");
}
}
 
fn main() {
safe_wrapper();
with_cleanup();
}
Erklärung
1
catch_unwind(AssertUnwindSafe(||
Wrapper für wiederherstellbare Panic-Erkennung
2
Ok(Ok(value))
Dreifach verschachtelt: keine Panic, kein Fehler, enthält Wert
3
Err(_) => println!("Panic war gefangen!")
Panic-Nutzlast gefangen, Thread fährt fort
4
struct Resource impl Drop
Destruktor-Garantie auch während Panic-Entladung
5
result.is_err()
Prüfen ob Panic auftrat ohne Nutzlast zu lesen