为什么futures::lock::Mutex未实现RefUnwindSafe trait
为什么futures::lock::Mutex传入std::panic::catch_unwind会被判定为不安全
std::panic::catch_unwind的泛型约束要求传入的闭包必须实现UnwindSafe trait。按照Rust类型系统的规则:如果闭包捕获了类型T的不可变引用,那么闭包满足UnwindSafe的前提是T实现了RefUnwindSafe trait。
futures::lock::Mutex默认没有实现RefUnwindSafe,因此编译器会直接拒绝下述代码的编译,判定该操作存在安全风险:
use std::panic::catch_unwind; use futures::lock::Mutex; fn main() { let m = Mutex::new(String::new()); catch_unwind(|| { m.lock() }); }
官方没有给该类型默认实现RefUnwindSafe的核心原因是:futures::lock::Mutex的内部实现用到了unsafe裸指针操作和自定义同步逻辑,维护者无法证明在所有通用使用场景下,持有Mutex不可变引用时发生panic,都不会破坏内部状态、引发悬垂指针或数据竞争等未定义行为,因此没有主动添加这个trait实现。
futures::lock::Mutex是否可以实现RefUnwindSafe trait
可以,但需要你自行承担安全校验责任:
- 官方默认没有提供实现,是为了避免通用场景下的误用风险,并不代表该类型在所有场景下都不符合
RefUnwindSafe的要求。 - 如果你能明确保证你的使用流程中,哪怕发生panic也不会破坏
Mutex的内部状态(比如仅使用标准的lock()接口、依赖MutexGuard的RAII机制自动释放锁,没有手动操作Mutex内部字段的逻辑),你可以通过newtype包装的方式,手动unsafe为包装类型实现RefUnwindSafe:
use futures::lock::Mutex; use std::panic::RefUnwindSafe; // 自定义包装类型 struct MyMutex<T>(Mutex<T>); // 手动实现RefUnwindSafe,安全性由自己保证 unsafe impl<T> RefUnwindSafe for MyMutex<T> {}
内容的提问来源于stack exchange,提问作者allevo
相关产品推荐
相关产品推荐

