Rust Panic::catch_unwind 在 WebAssembly 中没有用

聂小涛*_*聂小涛 5 rust webassembly

我尝试使用panic::catch_unwind捕获一些错误,但似乎没有用,并且有一个例子:

锈:

use std::{sync::Mutex};
use wasm_bindgen::prelude::*;
use std::sync::PoisonError;
use std::panic;

pub struct CurrentStatus {
  pub index: i32,
}

#[wasm_bindgen]
extern {
  pub fn alert(s: &str);
}


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);
  let result = panic::catch_unwind(|| {
    panic!("error happen!"); // original panic! code
  });
  if result.is_err() {
    alert("panic!!!!!panic");
  }
  return foo.get_index();
}
Run Code Online (Sandbox Code Playgroud)

js:

const js = import("../pkg/hello_wasm.js");
js.then(js => {
  window.js = js;
  console.log(js.get_index());
  js.add_index();
});
Run Code Online (Sandbox Code Playgroud)

我认为它应该引起恐慌,add_index然后我可以打电话。

但事实上,在恐慌之后我都无法打电话。

我希望我能从一个函数中捕获恐慌,这样当用户调用其他函数时就可以了。

非常感谢

Pet*_*man 1

默认情况下,wasm 构建设置为panic=abort,即退出程序,即使存在catch_unwind.

从这个 prpanic=unwind开始可以设置,但仅限于板条箱。[no_std]

如果你确实需要,有一些方法可以解决它,例如wasm-bindgen 自己的测试箱使用 捕获恐慌scoped-tls,它看起来像这样:

scoped_tls::scoped_thread_local!(static CURRENT_OUTPUT: RefCell<Output>);

static SET_HOOK: Once = Once::new();
SET_HOOK.call_once(|| {
    std::panic::set_hook(Box::new(|panic_info| {
        let should_panic = CURRENT_OUTPUT.with(|output| {
            let mut output = output.borrow_mut();
            output.panic.push_str(&panic_info.to_string());
            output.should_panic
        });

        if !should_panic {
           console_error_panic_hook::hook(panic_info);
        }
    }));
});

let result = CURRENT_OUTPUT.set(&output, || {
    let mut test = Some(test);
    __wbg_test_invoke(&mut || {
        let test = test.take().unwrap_throw();
        future_output = Some(test.poll(cx))
    })
});
Run Code Online (Sandbox Code Playgroud)