diff options
-rw-r--r-- | ports/libsimpleservo/capi/src/lib.rs | 209 |
1 files changed, 131 insertions, 78 deletions
diff --git a/ports/libsimpleservo/capi/src/lib.rs b/ports/libsimpleservo/capi/src/lib.rs index e415550e5f6..33013164409 100644 --- a/ports/libsimpleservo/capi/src/lib.rs +++ b/ports/libsimpleservo/capi/src/lib.rs @@ -15,6 +15,12 @@ use simpleservo::{Coordinates, EventLoopWaker, HostTrait, InitOptions, VRInitOpt use std::ffi::{CStr, CString}; use std::mem; use std::os::raw::{c_char, c_void}; +use std::panic::{self, AssertUnwindSafe, UnwindSafe}; + +/// Catch any panic function used by extern "C" functions. +fn catch_any_panic<F: FnOnce() + UnwindSafe>(function: F) -> bool { + panic::catch_unwind(function).is_ok() +} fn call<F>(f: F) where @@ -66,11 +72,18 @@ pub struct CInitOptions { /// The returned string is not freed. This will leak. #[no_mangle] pub extern "C" fn servo_version() -> *const c_char { - let v = simpleservo::servo_version(); - let text = CString::new(v).expect("Can't create string"); - let ptr = text.as_ptr(); - mem::forget(text); - ptr + let result = panic::catch_unwind(AssertUnwindSafe(|| { + let v = simpleservo::servo_version(); + let text = CString::new(v).expect("Can't create string"); + let ptr: *const c_char = text.as_ptr(); + mem::forget(text); + ptr + })); + + match result { + Ok(ptr) => ptr, + Err(_) => std::ptr::null(), + } } #[cfg(target_os = "windows")] @@ -146,19 +159,21 @@ pub extern "C" fn init_with_egl( opts: CInitOptions, wakeup: extern "C" fn(), callbacks: CHostCallbacks, -) { - init_logger(); - let gl = gl_glue::egl::init().unwrap(); - unsafe { - init( - opts, - gl.gl_wrapper, - Some(gl.gl_context), - Some(gl.display), - wakeup, - callbacks, - ) - } +) -> bool { + catch_any_panic(|| { + init_logger(); + let gl = gl_glue::egl::init().unwrap(); + unsafe { + init( + opts, + gl.gl_wrapper, + Some(gl.gl_context), + Some(gl.display), + wakeup, + callbacks, + ) + } + }) } #[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))] @@ -167,10 +182,12 @@ pub extern "C" fn init_with_gl( opts: CInitOptions, wakeup: extern "C" fn(), callbacks: CHostCallbacks, -) { - init_logger(); - let gl = gl_glue::gl::init().unwrap(); - unsafe { init(opts, gl, None, None, wakeup, callbacks) } +) -> bool { + catch_any_panic(|| { + init_logger(); + let gl = gl_glue::gl::init().unwrap(); + unsafe { init(opts, gl, None, None, wakeup, callbacks) } + }) } #[no_mangle] @@ -201,113 +218,149 @@ pub extern "C" fn resize(width: i32, height: i32) { } #[no_mangle] -pub extern "C" fn perform_updates() { - debug!("perform_updates"); - call(|s| s.perform_updates()); +pub extern "C" fn perform_updates() -> bool { + catch_any_panic(|| { + debug!("perform_updates"); + call(|s| s.perform_updates()); + }) } #[no_mangle] -pub extern "C" fn load_uri(url: *const c_char) { - debug!("load_url"); - let url = unsafe { CStr::from_ptr(url) }; - let url = url.to_str().expect("Can't read string"); - call(|s| s.load_uri(url)); +pub extern "C" fn load_uri(url: *const c_char) -> bool { + catch_any_panic(|| { + debug!("load_url"); + let url = unsafe { CStr::from_ptr(url) }; + let url = url.to_str().expect("Can't read string"); + call(|s| s.load_uri(url)); + }) } #[no_mangle] -pub extern "C" fn reload() { - debug!("reload"); - call(|s| s.reload()); +pub extern "C" fn reload() -> bool { + catch_any_panic(|| { + debug!("reload"); + call(|s| s.reload()); + }) } #[no_mangle] -pub extern "C" fn stop() { - debug!("stop"); - call(|s| s.stop()); +pub extern "C" fn stop() -> bool { + catch_any_panic(|| { + debug!("stop"); + call(|s| s.stop()); + }) } #[no_mangle] -pub extern "C" fn refresh() { - debug!("refresh"); - call(|s| s.refresh()); +pub extern "C" fn refresh() -> bool { + catch_any_panic(|| { + debug!("refresh"); + call(|s| s.refresh()); + }) } #[no_mangle] -pub extern "C" fn go_back() { - debug!("go_back"); - call(|s| s.go_back()); +pub extern "C" fn go_back() -> bool { + catch_any_panic(|| { + debug!("go_back"); + call(|s| s.go_back()); + }) } #[no_mangle] -pub extern "C" fn go_forward() { - debug!("go_forward"); - call(|s| s.go_forward()); +pub extern "C" fn go_forward() -> bool { + catch_any_panic(|| { + debug!("go_forward"); + call(|s| s.go_forward()); + }) } #[no_mangle] -pub extern "C" fn scroll_start(dx: i32, dy: i32, x: i32, y: i32) { - debug!("scroll_start"); - call(|s| s.scroll_start(dx as f32, dy as f32, x, y)); +pub extern "C" fn scroll_start(dx: i32, dy: i32, x: i32, y: i32) -> bool { + catch_any_panic(|| { + debug!("scroll_start"); + call(|s| s.scroll_start(dx as f32, dy as f32, x, y)); + }) } #[no_mangle] -pub extern "C" fn scroll_end(dx: i32, dy: i32, x: i32, y: i32) { - debug!("scroll_end"); - call(|s| s.scroll_end(dx as f32, dy as f32, x, y)); +pub extern "C" fn scroll_end(dx: i32, dy: i32, x: i32, y: i32) -> bool { + catch_any_panic(|| { + debug!("scroll_end"); + call(|s| s.scroll_end(dx as f32, dy as f32, x, y)); + }) } #[no_mangle] -pub extern "C" fn scroll(dx: i32, dy: i32, x: i32, y: i32) { - debug!("scroll"); - call(|s| s.scroll(dx as f32, dy as f32, x, y)); +pub extern "C" fn scroll(dx: i32, dy: i32, x: i32, y: i32) -> bool { + catch_any_panic(|| { + debug!("scroll"); + call(|s| s.scroll(dx as f32, dy as f32, x, y)); + }) } #[no_mangle] -pub extern "C" fn touch_down(x: f32, y: f32, pointer_id: i32) { - debug!("touch down"); - call(|s| s.touch_down(x, y, pointer_id)); +pub extern "C" fn touch_down(x: f32, y: f32, pointer_id: i32) -> bool { + catch_any_panic(|| { + debug!("touch down"); + call(|s| s.touch_down(x, y, pointer_id)); + }) } #[no_mangle] -pub extern "C" fn touch_up(x: f32, y: f32, pointer_id: i32) { - debug!("touch up"); - call(|s| s.touch_up(x, y, pointer_id)); +pub extern "C" fn touch_up(x: f32, y: f32, pointer_id: i32) -> bool { + catch_any_panic(|| { + debug!("touch up"); + call(|s| s.touch_up(x, y, pointer_id)); + }) } #[no_mangle] -pub extern "C" fn touch_move(x: f32, y: f32, pointer_id: i32) { - debug!("touch move"); - call(|s| s.touch_move(x, y, pointer_id)); +pub extern "C" fn touch_move(x: f32, y: f32, pointer_id: i32) -> bool { + catch_any_panic(|| { + debug!("touch move"); + call(|s| s.touch_move(x, y, pointer_id)); + }) } #[no_mangle] -pub extern "C" fn touch_cancel(x: f32, y: f32, pointer_id: i32) { - debug!("touch cancel"); - call(|s| s.touch_cancel(x, y, pointer_id)); +pub extern "C" fn touch_cancel(x: f32, y: f32, pointer_id: i32) -> bool { + catch_any_panic(|| { + debug!("touch cancel"); + call(|s| s.touch_cancel(x, y, pointer_id)); + }) } #[no_mangle] -pub extern "C" fn pinchzoom_start(factor: f32, x: i32, y: i32) { - debug!("pinchzoom_start"); - call(|s| s.pinchzoom_start(factor, x as u32, y as u32)); +pub extern "C" fn pinchzoom_start(factor: f32, x: i32, y: i32) -> bool { + catch_any_panic(|| { + debug!("pinchzoom_start"); + call(|s| s.pinchzoom_start(factor, x as u32, y as u32)); + }) } #[no_mangle] -pub extern "C" fn pinchzoom(factor: f32, x: i32, y: i32) { - debug!("pinchzoom"); - call(|s| s.pinchzoom(factor, x as u32, y as u32)); +pub extern "C" fn pinchzoom(factor: f32, x: i32, y: i32) -> bool { + catch_any_panic(|| { + debug!("pinchzoom"); + call(|s| s.pinchzoom(factor, x as u32, y as u32)); + }) } #[no_mangle] -pub extern "C" fn pinchzoom_end(factor: f32, x: i32, y: i32) { - debug!("pinchzoom_end"); - call(|s| s.pinchzoom_end(factor, x as u32, y as u32)); +pub extern "C" fn pinchzoom_end(factor: f32, x: i32, y: i32) -> bool { + catch_any_panic(|| { + debug!("pinchzoom_end"); + call(|s| s.pinchzoom_end(factor, x as u32, y as u32)); + }) } #[no_mangle] -pub extern "C" fn click(x: i32, y: i32) { - debug!("click"); - call(|s| s.click(x as f32, y as f32)); +pub extern "C" fn click(x: i32, y: i32) -> bool { + catch_any_panic(|| { + debug!("click"); + call(|s| s.click(x as f32, y as f32)); + }) } pub struct WakeupCallback(extern "C" fn()); |