在Rust最新的稳定版中,@ for1096的答案是最好的。在你的情况,因为你清理不需要使用与应用程序代码共享状态时,它可能是很简单的应用:
use std::panic::catch_unwind;
fn run_editor(){
panic!("Error!");
println!("Running!");
}
fn clean_up(){
println!("Cleaning up!");
}
fn main(){
match catch_unwind(|| run_editor()) {
Ok(_) => println!("Exited successfully"),
Err(_) => clean_up()
}
}
如果您的清理需要访问你的应用程序共享的状态,那么你将需要一些额外的机制来说服编译器它是安全的。例如,如果你的程序是这样的:
// The shared state of your application
struct Editor { /* ... */ }
impl Editor {
fn run(&mut self){
println!("running!");
// panic!("Error!");
}
fn clean_up(&mut self){
println!("cleaning up!");
}
fn new() -> Editor {
Editor { }
}
}
然后,为了调用clean_up
,你就必须管理对数据的访问,是这样的:
use std::panic::catch_unwind;
use std::sync::{Arc, Mutex};
fn main() {
let editor = Arc::new(Mutex::new(Editor::new()));
match catch_unwind(|| editor.lock().unwrap().run()) {
Ok(_) => println!("Exited successfully"),
Err(_) => {
println!("Application panicked.");
let mut editor = match editor.lock() {
Ok(guard) => guard,
Err(poisoned) => poisoned.into_inner(),
};
editor.clean_up();
}
}
}
此前生锈1.9 ,你只能处理发生在子线程中的恐慌。除了你需要克隆Arc
之外,这并没有什么不同,因为原来的那个需要在线程关闭中变成move
d。
use std::thread;
use std::sync::{Arc, Mutex};
fn main() {
let editor = Arc::new(Mutex::new(Editor::new()));
// clone before the original is moved into the thread closure
let editor_recovery = editor.clone();
let child = thread::spawn(move || {
editor.lock().unwrap().run();
});
match child.join() {
Ok(_) => println!("Exited successfully"),
Err(_) => {
println!("Application panicked.");
let mut editor = match editor_recovery.lock() {
Ok(guard) => guard,
Err(poisoned) => poisoned.into_inner(),
};
editor.clean_up();
}
}
}
您可以创建一个新线程来运行您的应用程序。主应用程序线程几乎没有任何可能出错的地方,并且可以在发生混乱时清理并重新启动子线程。 –