抓狂!当Rust从C FFI调用时,没有产生线程

emk*_*emk 9 error-handling multithreading ffi stack-unwinding rust

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

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

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

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

Benjamin Herr提出的一个解决方案是,如果(5)中的代码恐慌,则中止该过程.我已经将他的解决方案打包abort_on_panic为"工作"的价值,它似乎有效,包括"崩溃整个程序,但至少不会巧妙地破坏事物":

abort_on_panic!("cannot panic inside this block", {
    panic!("something went wrong!");
});
Run Code Online (Sandbox Code Playgroud)

但是,这是一种模拟std::task::try没有线程/任务创建的开销的方法吗?

dra*_*tis 7

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

use std::panic;

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

将它传递到下一层同样容易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);
    }
}
Run Code Online (Sandbox Code Playgroud)