#thread #panic #applications #gamedev

panik

全应用范围内的panic处理,其中任何线程发生的panic都被视为硬错误,其他线程可以检测到并触发优雅退出

3个不稳定版本

0.2.0 2021年2月9日
0.1.1 2021年2月9日
0.1.0 2021年2月6日

#937 in 游戏开发

MIT 协议

25KB
289

panik-rs

Build Status Documentation Version License

此crate实现全应用范围内的panic处理,其中任何线程发生的panic都会被捕获并存储,之后可以查询以触发早期应用退出。

这与标准panic行为相反,在标准panic行为中,panic仅限于导致panic的线程。此库引入的条件是任何线程的panic都是错误,应用无法继续或恢复。

用例

此crate的主要用例是当一个线程创建了多个线程来执行工作,并在它们完成时阻塞。如果工作线程在结果发布之前panic,等待的线程可能会在recv的阻塞调用中卡住,除非它专门计划和检查这种错误情况(例如,poisoned mutex,断开mpsc发送者)。

在一个大型应用中,如具有线程池和大量工作被提交的应用(如游戏引擎),正确处理每个panic情况可能很困难。使用此库允许主线程在其核心游戏循环中轮询panic,并优雅地退出,而不是在没有音频/渲染/AI/工作线程的情况下继续前进。

未使用panic检测且永久挂起的示例

let (tx, rx) = std::sync::mpsc::channel();
let worker = std::thread::spawn(move || {
    // hopefully do some work...
    // tx.send(5).unwrap();

    // ...or panic and hold up the main thread forever
    todo!()
});

let result: i32 = rx.recv().expect("recv failed"); // blocks forever
println!("result: {}", result);

检测和处理panic并优雅退出的相同示例

let application_result = panik::run_and_handle_panics(|| {
    let (tx, rx) = std::sync::mpsc::channel();
    let worker = std::thread::spawn(move || {
        // do some work...
        // tx.send(5).unwrap();

        // ...or panic and hold up the main thread forever
        todo!()
    });

    // periodically check if a panic has occurred
    let poll_freq = Duration::from_secs(5);
    while !panik::has_panicked() {
        if let Ok(res) = rx.recv_timeout(poll_freq) {
            return res;
        }
    }

    // return value is irrelevant here, the panic on the worker
    // thread will clobber this when `run_and_handle_panics`
    // returns None
    0
});

match application_result {
    None => {
        eprintln!("something went wrong: {:?}", panik::panics());
        std::process::exit(1);
    },
    Some(result) => {
        println!("result: {}", result);
        std::process::exit(0);
    }
}

这看起来相当重量级,但这是故意的 - 此库是为大型且重量级的应用而设计的!

功能

  • use-stderr:将panic记录到stderr
  • use-log:使用log crate记录panic
  • use-slog:使用slog crate记录panic(请参阅Builder::slogger
  • use-parking-lot:使用parking_lot::Mutex代替std::sync::Mutex

依赖关系

~2.5–4MB
~77K SLoC