1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-24 08:09:08 -05:00

fix(core): handle exception from Wasm termination (#15014)

Co-authored-by: Augusto Lenz <augustollenz@gmail.com>
This commit is contained in:
João Avelino Bellomo Filho 2022-07-01 04:51:29 -03:00 committed by David Sherret
parent f92b2dc053
commit 68d50f964a

View file

@ -785,7 +785,7 @@ impl JsRuntime {
} }
} }
fn pump_v8_message_loop(&mut self) { fn pump_v8_message_loop(&mut self) -> Result<(), Error> {
let scope = &mut self.handle_scope(); let scope = &mut self.handle_scope();
while v8::Platform::pump_message_loop( while v8::Platform::pump_message_loop(
&v8::V8::get_current_platform(), &v8::V8::get_current_platform(),
@ -795,7 +795,12 @@ impl JsRuntime {
// do nothing // do nothing
} }
scope.perform_microtask_checkpoint(); let tc_scope = &mut v8::TryCatch::new(scope);
tc_scope.perform_microtask_checkpoint();
match tc_scope.exception() {
None => Ok(()),
Some(exception) => exception_to_err_result(tc_scope, exception, false),
}
} }
pub fn poll_value( pub fn poll_value(
@ -877,7 +882,7 @@ impl JsRuntime {
state.waker.register(cx.waker()); state.waker.register(cx.waker());
} }
self.pump_v8_message_loop(); self.pump_v8_message_loop()?;
// Ops // Ops
{ {
@ -2273,6 +2278,56 @@ pub mod tests {
); );
} }
#[test]
fn terminate_execution_webassembly() {
let (mut isolate, _dispatch_count) = setup(Mode::Async);
let v8_isolate_handle = isolate.v8_isolate().thread_safe_handle();
let terminator_thread = std::thread::spawn(move || {
// allow deno to boot and run
std::thread::sleep(std::time::Duration::from_millis(1000));
// terminate execution
let ok = v8_isolate_handle.terminate_execution();
assert!(ok);
});
// Run an infinite loop in Webassemby code, which should be terminated.
isolate.execute_script("infinite_wasm_loop.js",
r#"
(async () => {
console.log("Begin");
const wasmCode = new Uint8Array([
0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1,
96, 0, 0, 3, 2, 1, 0, 7, 17, 1, 13,
105, 110, 102, 105, 110, 105, 116, 101, 95, 108, 111,
111, 112, 0, 0, 10, 9, 1, 7, 0, 3, 64,
12, 0, 11, 11,
]);
const wasmModule = await WebAssembly.compile(wasmCode);
const wasmInstance = new WebAssembly.Instance(wasmModule);
wasmInstance.exports.infinite_loop();
})();
"#).expect("wasm infinite loop failed");
match futures::executor::block_on(isolate.run_event_loop(false)) {
Ok(_) => panic!("execution should be terminated"),
Err(e) => {
assert_eq!(e.to_string(), "Uncaught Error: execution terminated")
}
}
// Cancel the execution-terminating exception in order to allow script
// execution again.
let ok = isolate.v8_isolate().cancel_terminate_execution();
assert!(ok);
// Verify that the isolate usable again.
isolate
.execute_script("simple.js", "1 + 1")
.expect("execution should be possible again");
terminator_thread.join().unwrap();
}
#[test] #[test]
fn terminate_execution() { fn terminate_execution() {
let (mut isolate, _dispatch_count) = setup(Mode::Async); let (mut isolate, _dispatch_count) = setup(Mode::Async);