我正在为Duktape JavaScript解释器编写Rust包装器(https://github.com/emk/duktape-rs)。在正常使用情况下,调用堆栈将如下所示:
- Rust:任意应用程序代码。
- Rust:我的库包装器。
- C:Duktape解释器。
- Rust:我的Rust代码。
- Rust:进入应用程序代码的任意回调。
如果(5)从内部非Rust调用帧中调用panic!
会发生什么?根据IRC上的各种Rust开发人员的说法,尝试从像(3)这样的非Rust调用帧内部调用panic!
可能会导致未定义的行为。
但是根据Rust文档,捕获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!");
});
但是有没有一种方法可以模拟std::task::try
的行为,而不需要创建线程或任务的开销呢?
std::task::try
是否真的需要实际生成一个新的操作系统线程?它似乎可以被实现为保存一些运行时状态,使用同一操作系统线程调用“任务”,并在完成时恢复运行时状态。这将保持与当前版本相同的公共API,但可能节省每次JavaScript调用Rust时调用pthread_new
的成本。 - emk