抓紧恐慌!当Rust从C FFI调用时,没有生成线程 [英] Catching panic! when Rust called from C FFI, without spawning threads
问题描述
我正在研究用于Duktape JavaScript解释器的锈纸包装器。在正常使用情况下,调用堆栈将如下所示:
I'm working on a Rust wrapper for the Duktape JavaScript interpreter. In a normal use case, the call stack will look like this:
- Rust:任意应用程序代码。
- Rust:我的库包装。
- C:Duktape解释器。
- Rust:我的Rust代码。
- Rust:任意回调到应用程序代码中。
- Rust: Arbitrary application code.
- Rust: My library wrapper.
- C: The Duktape interpreter.
- Rust: My Rust code.
- Rust: Arbitrary callbacks into application code.
如果(5)调用 panic,会发生什么情况!
?根据IRC上各种Rust开发人员的说法,尝试从非Rust调用框架(如(3))中 panic!
可能导致不确定的行为。
What happens if (5) calls panic!
? According to various Rust developers on IRC, attempting to panic!
from inside non-Rust callframes like (3) may result in undefined behavior.
但是根据Rust文档,捕获恐慌的唯一方法!
是使用 std :: task :: try
,这会产生一个额外的线程。还有 rustrt :: unwind :: try
,它不能在单个线程中嵌套两次,还有其他限制。
But according the Rust documentation, the only way to catch a panic!
is using std::task::try
, which spawns an extra thread. There's also rustrt::unwind::try
, which cannot be nested twice within a single thread, among other restrictions.
本杰明·赫尔(Benjamin Herr)提出的一种解决方案是,如果代码无效,则中止该进程在(5)恐慌中。我将他的解决方案打包为 abort_on_panic
,工作,对于工作的值包括使整个程序崩溃,但至少不会巧妙地破坏:
One solution, proposed by Benjamin Herr, is to abort the process if the code in (5) panics. I've packaged his solution as abort_on_panic
, and it appears to work, for values of "work" that include "crashing the entire program, but at least not corrupting things subtly":
abort_on_panic!("cannot panic inside this block", {
panic!("something went wrong!");
});
但这是一种模拟 std :: task :: try 的方法code>没有创建线程/任务的开销?
But is a way to emulate std::task::try
without the overhead of thread/task creation?
推荐答案
从Rust 1.9.0开始,您可以使用< a href = https://doc.rust-lang.org/std/panic/fn.catch_unwind.html rel = nofollow noreferrer> panic :: catch_unwind
恢复错误:
As of Rust 1.9.0, you can use panic::catch_unwind
to recover the error:
use std::panic;
fn main() {
let result = panic::catch_unwind(|| {
panic!("oh no!");
});
assert!(result.is_err());
}
use std::panic;
fn main() {
let result = panic::catch_unwind(|| {
panic!("oh no!");
});
if let Err(e) = result {
panic::resume_unwind(e);
}
}
这篇关于抓紧恐慌!当Rust从C FFI调用时,没有生成线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!