我在使用 rust + WebAssembly 开发的时候遇到了一个死锁问题
目前由于用到了一些全局访问的变量,我选择了 lazy_static (使用 thread_local 回调式的写法可能会造成嵌套问题)和 mutex,但我目前遇到了一个问题:
目前我在 rust 中声明了很多函数,通过 #[wasm_bindgen]
的方式供 js 调用,它们会读写一些 lazy_static 的变量
当其中的一个函数 panic 之后,对 mutex 的持有无法释放,导致其他函数如果需要用到这个 mutex,也会 panic
当然我知道 panic 的问题是意外的,并且需要修复的,但是实际上这些函数彼此比较独立,读写的 lazy_static 变量虽然有相交,但实际上某一处 bug 不一定会影响其他造成 bug
我的诉求是有没有一种方式,在 wasm 中 rust panic 之后触发释放 mutex,这样其他函数的调用会是正常的。
或者对于这类问题,有没有什么更好的实践?
谢谢~!
增加demo:
js:
const js = import("../pkg/hello_wasm.js");
js.then(js => {
window.js = js;
console.log(js.get_index());
js.add_index();
console.log(js.get_index());
js.add_index();
console.log(js.get_index());
js.add_index();
console.log(js.get_index());
js.add_index();
console.log(js.get_index());
js.add_index();
});
rust:
use std::{sync::Mutex};
use wasm_bindgen::prelude::*;
use std::sync::PoisonError;
pub struct CurrentStatus {
pub index: i32,
}
impl CurrentStatus {
fn new() -> Self {
CurrentStatus {
index: 1,
}
}
fn get_index(&mut self) -> i32 {
self.index += 1;
self.index.clone()
}
fn add_index(&mut self) {
self.index += 2;
}
}
lazy_static! {
pub static ref FOO: Mutex<CurrentStatus> = Mutex::new(CurrentStatus::new());
}
unsafe impl Send for CurrentStatus {}
#[wasm_bindgen]
pub fn add_index() {
FOO.lock().unwrap_or_else(PoisonError::into_inner).add_index();
}
#[wasm_bindgen]
pub fn get_index() -> i32 {
let mut foo = FOO.lock().unwrap_or_else(PoisonError::into_inner);
if foo.get_index() == 6 {
panic!();
}
return foo.get_index();
}
panic 之后,再也无法调用成功。。
1
共 2 条评论, 1 页
评论区
写评论能放点源码看看吗?
听起来是想从panic中恢复? 可以考虑用 std::panic::catch_unwind 把需要特殊处理的panic! wrap一下
类似如下代码: use std::panic;
不过这样比较啰嗦,panic!应该会触发drop, 在drop中做清理工作应该也可以