由于使用了一些全局访问的变量,我选择
lazy_static(使用thread_local回调可能会导致嵌套问题)和互斥锁,但我目前遇到了问题:
我已经在rust中声明了很多函数,这些函数由js通过# [wasm_bindgen]
使用。他们读写一些lazy_static变量。在其中一种功能出现紧急情况后,互斥量的保持无法释放,如果其他功能需要使用相同的互斥量,则会导致紧急情况。
当然,我知道恐慌问题是出乎意料的,需要解决,但是实际上,这些功能是相对独立的。尽管读写lazy_static变量相交,但实际上,某些错误可能不一定会影响其他部分。
我的呼吁是在wasm出现锈病恐慌后触发互斥锁释放的方式,这样其他js函数的调用就可以了。
或者对于这种问题有更好的做法吗?谢谢〜!
这允许程序立即终止并向程序的调用者提供反馈。恐慌!当程序达到不可恢复的状态时应使用。
Rust中的Panic实际上比来自C ++背景的人看起来要柔和得多(我认为有些人在评论中写这种情况)。默认情况下,未捕获的Rust恐慌会终止线程,而C ++异常会终止整个过程。
引用documentationRust中的致命逻辑错误会导致线程崩溃,在此期间,线程将展开堆栈,运行析构函数并释放拥有的资源。尽管这不意味着是“尝试/捕获”机制,但是Rust的恐慌仍然可以通过catch_unwind来捕获(除非使用panic = abort进行编译)并从catch_unwind中恢复,或者通过resume_unwind恢复。如果未捕获到紧急情况,则线程将退出,但可以选择通过具有join的其他线程来检测紧急情况。如果主线程出现紧急情况而没有捕获到紧急情况,则应用程序将以非零的退出代码退出。
catch_unwind可以从紧急情况中恢复线程,但是您应该知道,不能保证catch_unwind
能够捕获所有紧急情况。
请注意,此功能可能无法捕获Rust中的所有紧急情况。 Rust中的恐慌并不总是通过平仓来实现,但是也可以通过中止该过程来实现。此功能仅捕获正在缓解的紧急情况,而不会中止该过程的紧急情况。
因此,我们了解从恐慌中恢复是可以的。问题是锁中毒时该怎么办。
引用documentation此模块中的互斥锁实施一种称为“中毒”的策略,只要线程在按住该互斥锁时发生紧急情况,该互斥锁即被视为有毒。一旦互斥体中毒,默认情况下,所有其他线程都无法访问数据,因为它很可能已被污染(某些不变性未被维护)。
存在中毒的正当理由,因为可能不会保留您数据的不变性。考虑某些功能中间的panic!
。这只是您可以绕过的附加安全级别。
但是,中毒的互斥锁不会阻止对底层数据的所有访问。 PoisonError类型具有int_inner方法,该方法将返回保护,否则将在成功锁定后返回该保护。尽管锁被中毒,这仍允许访问数据。
use std::sync::{Mutex, PoisonError};
fn main() {
let mutex = Mutex::new(1);
// We are prepared to face bugs if invariants are wrong
println!("{}", mutex.lock().unwrap_or_else(PoisonError::into_inner));
}
Playground link当然,解决恐慌总比这样做好。