11

我正在为 Duktape JavaScript 解释器开发一个 Rust 包装器。在正常用例中,调用堆栈将如下所示:

  1. Rust:任意应用程序代码。
  2. Rust:我的库包装器。
  3. C: Duktape 口译员。
  4. Rust:我的 Rust 代码。
  5. Rust:应用程序代码中的任意回调。

如果 (5) 调用会发生什么panic!?根据 IRC 上的各种 Rust 开发人员的说法,尝试panic!从像 (3) 这样的非 Rust 调用框架内部可能会导致未定义的行为。

但是根据 Rust 文档,捕获 a 的唯一方法panic!是 using std::task::try,它会产生一个额外的线程。除了其他限制外,还有rustrt::unwind::try, 它不能在单个线程中嵌套两次。

Benjamin Herr 提出的一种解决方案是,如果 (5) 中的代码出现恐慌,则中止该过程。我已经将他的解决方案打包为abort_on_panic,并且它似乎可以工作,对于“工作”的价值,包括“使整个程序崩溃,但至少不会巧妙地破坏事物”:

abort_on_panic!("cannot panic inside this block", {
    panic!("something went wrong!");
});

但是,是一种std::task::try无需创建线程/任务开销即可进行模拟的方法吗?

4

2 回答 2

9

从 Rust 1.9.0 开始,您可以使用panic::catch_unwind来恢复错误:

use std::panic;

fn main() {
    let result = panic::catch_unwind(|| {
        panic!("oh no!");
    });
    assert!(result.is_err());
}

将其传递到下一层同样简单panic::resume_unwind

use std::panic;

fn main() {
    let result = panic::catch_unwind(|| {
        panic!("oh no!");
    });

    if let Err(e) = result {
        panic::resume_unwind(e);
    }
}
于 2016-03-19T15:59:33.573 回答
4

Editor's note: This answer predates Rust 1.0 and is no longer necessarily accurate. Other answers still contain valuable information.

You cannot 'catch' a panic!. It terminates execution of the current thread. Therefore, without spinning up a new one to isolate, it's going to terminate the thread you're in.

于 2014-12-11T12:57:27.017 回答