mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-28 16:11:32 +00:00
Removed unnecessary files
This commit is contained in:
@ -1,17 +0,0 @@
|
|||||||
/// Round `size` up to the nearest multiple of `page_size`.
|
|
||||||
pub fn round_up_to_page_size(size: usize, page_size: usize) -> usize {
|
|
||||||
(size + (page_size - 1)) & !(page_size - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_round_up_to_page_size() {
|
|
||||||
assert_eq!(round_up_to_page_size(0, 4096), 0);
|
|
||||||
assert_eq!(round_up_to_page_size(1, 4096), 4096);
|
|
||||||
assert_eq!(round_up_to_page_size(4096, 4096), 4096);
|
|
||||||
assert_eq!(round_up_to_page_size(4097, 4096), 8192);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
//! A cross-platform Rust API for memory mapped buffers.
|
|
||||||
// TODO: Refactor this into it's own lib
|
|
||||||
mod common;
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
mod windows;
|
|
||||||
#[cfg(windows)]
|
|
||||||
pub use self::windows::Mmap;
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
mod unix;
|
|
||||||
#[cfg(unix)]
|
|
||||||
pub use self::unix::Mmap;
|
|
@ -1,95 +0,0 @@
|
|||||||
//! Low-level abstraction for allocating and managing zero-filled pages
|
|
||||||
//! of memory.
|
|
||||||
|
|
||||||
use errno;
|
|
||||||
use libc;
|
|
||||||
use region;
|
|
||||||
use std::ptr;
|
|
||||||
use std::slice;
|
|
||||||
use std::string::String;
|
|
||||||
|
|
||||||
use super::common::round_up_to_page_size;
|
|
||||||
|
|
||||||
/// A simple struct consisting of a page-aligned pointer to page-aligned
|
|
||||||
/// and initially-zeroed memory and a length.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Mmap {
|
|
||||||
ptr: *mut u8,
|
|
||||||
len: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mmap {
|
|
||||||
/// Construct a new empty instance of `Mmap`.
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
ptr: ptr::null_mut(),
|
|
||||||
len: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new `Mmap` pointing to at least `size` bytes of memory,
|
|
||||||
/// suitably sized and aligned for memory protection.
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
pub fn with_size(size: usize) -> Result<Self, String> {
|
|
||||||
// Mmap may return EINVAL if the size is zero, so just
|
|
||||||
// special-case that.
|
|
||||||
if size == 0 {
|
|
||||||
return Ok(Self::new());
|
|
||||||
}
|
|
||||||
|
|
||||||
let page_size = region::page::size();
|
|
||||||
let alloc_size = round_up_to_page_size(size, page_size);
|
|
||||||
let ptr = unsafe {
|
|
||||||
libc::mmap(
|
|
||||||
ptr::null_mut(),
|
|
||||||
alloc_size,
|
|
||||||
libc::PROT_NONE,
|
|
||||||
libc::MAP_PRIVATE | libc::MAP_ANON,
|
|
||||||
-1,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if ptr as isize == -1isize {
|
|
||||||
Err(errno::errno().to_string())
|
|
||||||
} else {
|
|
||||||
Ok(Self {
|
|
||||||
ptr: ptr as *mut u8,
|
|
||||||
len: alloc_size,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the allocated memory as a slice of u8.
|
|
||||||
pub fn as_slice(&self) -> &[u8] {
|
|
||||||
unsafe { slice::from_raw_parts(self.ptr, self.len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the allocated memory as a mutable slice of u8.
|
|
||||||
pub fn as_mut_slice(&mut self) -> &mut [u8] {
|
|
||||||
unsafe { slice::from_raw_parts_mut(self.ptr, self.len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the allocated memory as a pointer to u8.
|
|
||||||
pub fn as_ptr(&self) -> *const u8 {
|
|
||||||
self.ptr
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the allocated memory as a mutable pointer to u8.
|
|
||||||
pub fn as_mut_ptr(&mut self) -> *mut u8 {
|
|
||||||
self.ptr
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the lengthof the allocated memory.
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.len
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for Mmap {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if !self.ptr.is_null() {
|
|
||||||
let r = unsafe { libc::munmap(self.ptr as *mut libc::c_void, self.len) };
|
|
||||||
assert_eq!(r, 0, "munmap failed: {}", errno::errno());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
//! Low-level abstraction for allocating and managing zero-filled pages
|
|
||||||
//! of memory.
|
|
||||||
|
|
||||||
use errno;
|
|
||||||
use region;
|
|
||||||
use std::ptr;
|
|
||||||
use std::slice;
|
|
||||||
use std::string::String;
|
|
||||||
use winapi::um::memoryapi::{VirtualAlloc, VirtualFree};
|
|
||||||
use winapi::um::winnt::{MEM_COMMIT, MEM_RELEASE, MEM_RESERVE, PAGE_NOACCESS};
|
|
||||||
|
|
||||||
use super::common::round_up_to_page_size;
|
|
||||||
|
|
||||||
/// A simple struct consisting of a page-aligned pointer to page-aligned
|
|
||||||
/// and initially-zeroed memory and a length.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Mmap {
|
|
||||||
ptr: *mut u8,
|
|
||||||
len: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mmap {
|
|
||||||
/// Construct a new empty instance of `Mmap`.
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
ptr: ptr::null_mut(),
|
|
||||||
len: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new `Mmap` pointing to at least `size` bytes of memory,
|
|
||||||
/// suitably sized and aligned for memory protection.
|
|
||||||
pub fn with_size(size: usize) -> Result<Self, String> {
|
|
||||||
let page_size = region::page::size();
|
|
||||||
|
|
||||||
// VirtualAlloc always rounds up to the next multiple of the page size
|
|
||||||
let ptr = unsafe {
|
|
||||||
VirtualAlloc(
|
|
||||||
ptr::null_mut(),
|
|
||||||
size,
|
|
||||||
MEM_COMMIT | MEM_RESERVE,
|
|
||||||
PAGE_NOACCESS,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if !ptr.is_null() {
|
|
||||||
Ok(Self {
|
|
||||||
ptr: ptr as *mut u8,
|
|
||||||
len: round_up_to_page_size(size, page_size),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(errno::errno().to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the allocated memory as a slice of u8.
|
|
||||||
pub fn as_slice(&self) -> &[u8] {
|
|
||||||
unsafe { slice::from_raw_parts(self.ptr, self.len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the allocated memory as a mutable slice of u8.
|
|
||||||
pub fn as_mut_slice(&mut self) -> &mut [u8] {
|
|
||||||
unsafe { slice::from_raw_parts_mut(self.ptr, self.len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the allocated memory as a pointer to u8.
|
|
||||||
pub fn as_ptr(&self) -> *const u8 {
|
|
||||||
self.ptr
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the allocated memory as a mutable pointer to u8.
|
|
||||||
pub fn as_mut_ptr(&mut self) -> *mut u8 {
|
|
||||||
self.ptr
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the lengthof the allocated memory.
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.len
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for Mmap {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if !self.ptr.is_null() {
|
|
||||||
let r = unsafe { VirtualFree(self.ptr, self.len, MEM_RELEASE) };
|
|
||||||
assert_eq!(r, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
pub mod mmap;
|
|
||||||
pub mod slice;
|
|
@ -1,106 +0,0 @@
|
|||||||
use std::ops::{Index, IndexMut};
|
|
||||||
use std::ptr::NonNull;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct UncheckedSlice<T> {
|
|
||||||
ptr: NonNull<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> UncheckedSlice<T> {
|
|
||||||
#[inline]
|
|
||||||
pub fn get_unchecked(&self, index: usize) -> &T {
|
|
||||||
let ptr = self.ptr.as_ptr();
|
|
||||||
unsafe { &*ptr.add(index) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
|
|
||||||
let ptr = self.ptr.as_ptr();
|
|
||||||
unsafe { &mut *(ptr.add(index) as *mut _) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn dangling() -> UncheckedSlice<T> {
|
|
||||||
UncheckedSlice {
|
|
||||||
ptr: NonNull::dangling(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_ptr(&self) -> *const T {
|
|
||||||
self.ptr.as_ptr()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_mut_ptr(&mut self) -> *mut T {
|
|
||||||
self.ptr.as_ptr()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> From<&'a [T]> for UncheckedSlice<T> {
|
|
||||||
fn from(slice: &[T]) -> UncheckedSlice<T> {
|
|
||||||
let ptr: NonNull<[T]> = slice.into();
|
|
||||||
UncheckedSlice { ptr: ptr.cast() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct BoundedSlice<T> {
|
|
||||||
pub data: UncheckedSlice<T>,
|
|
||||||
pub len: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> BoundedSlice<T> {
|
|
||||||
pub fn get(&self, index: usize) -> Option<&T> {
|
|
||||||
if index < self.len {
|
|
||||||
Some(self.data.get_unchecked(index))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
|
|
||||||
if index < self.len {
|
|
||||||
Some(self.data.get_unchecked_mut(index))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.len
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Needs refactor. Take LinearMemory as argument.
|
|
||||||
// I've tried that but it gives cryptic error.
|
|
||||||
pub fn new(slice: &[T], size: usize) -> BoundedSlice<T> {
|
|
||||||
BoundedSlice {
|
|
||||||
data: slice.into(),
|
|
||||||
len: size,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Index<usize> for BoundedSlice<T> {
|
|
||||||
type Output = T;
|
|
||||||
fn index(&self, index: usize) -> &T {
|
|
||||||
self.get(index)
|
|
||||||
.unwrap_or_else(|| panic!("index: {} was out of bounds.", index))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> IndexMut<usize> for BoundedSlice<T> {
|
|
||||||
fn index_mut(&mut self, index: usize) -> &mut T {
|
|
||||||
self.get_mut(index)
|
|
||||||
.unwrap_or_else(|| panic!("index: {} was out of bounds.", index))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> From<&'a [T]> for BoundedSlice<T> {
|
|
||||||
fn from(slice: &[T]) -> BoundedSlice<T> {
|
|
||||||
BoundedSlice {
|
|
||||||
data: slice.into(),
|
|
||||||
len: slice.len(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +1,8 @@
|
|||||||
extern crate libc;
|
|
||||||
extern crate region;
|
|
||||||
extern crate wasmer_runtime;
|
extern crate wasmer_runtime;
|
||||||
// extern crate wasmer_emscripten;
|
// extern crate wasmer_emscripten;
|
||||||
|
|
||||||
pub extern crate nix; // re-exported for usage in macros
|
|
||||||
#[cfg(windows)]
|
|
||||||
extern crate winapi;
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod recovery;
|
|
||||||
pub mod common;
|
|
||||||
pub mod sighandler;
|
|
||||||
pub mod update;
|
pub mod update;
|
||||||
pub mod webassembly;
|
pub mod webassembly;
|
||||||
|
@ -1,24 +1,3 @@
|
|||||||
/// Retrieve a WebAssembly function given a Instance and a FuncIndex
|
|
||||||
/// Example:
|
|
||||||
/// let func: fn(i32) -> i32 = get_instance_function!(instance, func_index);
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! get_instance_function {
|
|
||||||
($instance:expr, $func_index:expr) => {{
|
|
||||||
use std::mem;
|
|
||||||
let func_addr = $instance.get_function_pointer($func_index);
|
|
||||||
unsafe { mem::transmute(func_addr) }
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! include_wast2wasm_bytes {
|
|
||||||
($x:expr) => {{
|
|
||||||
use wabt::wat2wasm;
|
|
||||||
const WAST_BYTES: &[u8] = include_bytes!($x);
|
|
||||||
wat2wasm(WAST_BYTES.to_vec()).expect(&format!("Can't convert {} file to wasm", $x))
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! debug {
|
macro_rules! debug {
|
||||||
($fmt:expr) => (if cfg!(any(debug_assertions, feature="debug")) { println!(concat!("Wasmer::", $fmt)) });
|
($fmt:expr) => (if cfg!(any(debug_assertions, feature="debug")) { println!(concat!("Wasmer::", $fmt)) });
|
||||||
|
122
src/recovery.rs
122
src/recovery.rs
@ -1,122 +0,0 @@
|
|||||||
//! When a WebAssembly module triggers any traps, we perform recovery here.
|
|
||||||
//!
|
|
||||||
//! This module uses TLS (thread-local storage) to track recovery information. Since the four signals we're handling
|
|
||||||
//! are very special, the async signal unsafety of Rust's TLS implementation generally does not affect the correctness here
|
|
||||||
//! unless you have memory unsafety elsewhere in your code.
|
|
||||||
|
|
||||||
use crate::sighandler::install_sighandler;
|
|
||||||
use nix::libc::siginfo_t;
|
|
||||||
use nix::sys::signal::{Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV};
|
|
||||||
use std::cell::{Cell, UnsafeCell};
|
|
||||||
use std::sync::Once;
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
pub fn setjmp(env: *mut ::nix::libc::c_void) -> ::nix::libc::c_int;
|
|
||||||
fn longjmp(env: *mut ::nix::libc::c_void, val: ::nix::libc::c_int) -> !;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SETJMP_BUFFER_LEN: usize = 27;
|
|
||||||
pub static SIGHANDLER_INIT: Once = Once::new();
|
|
||||||
|
|
||||||
thread_local! {
|
|
||||||
pub static SETJMP_BUFFER: UnsafeCell<[::nix::libc::c_int; SETJMP_BUFFER_LEN]> = UnsafeCell::new([0; SETJMP_BUFFER_LEN]);
|
|
||||||
pub static CAUGHT_ADDRESS: Cell<usize> = Cell::new(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need a macro since the arguments we will provide to the funciton
|
|
||||||
// (and the return value) are not fixed to just one case: f(x) -> y
|
|
||||||
// but multiple: f(x) -> y, f(a,b) -> c, ...
|
|
||||||
// And right now it's impossible to handle with Rust function type system
|
|
||||||
|
|
||||||
/// Calls a WebAssembly function with longjmp receiver installed. If a non-WebAssembly function is passed in,
|
|
||||||
/// the behavior of call_protected is undefined.
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! call_protected {
|
|
||||||
($x:expr) => {
|
|
||||||
unsafe {
|
|
||||||
use crate::recovery::{setjmp, CAUGHT_ADDRESS, SETJMP_BUFFER, SIGHANDLER_INIT};
|
|
||||||
use crate::sighandler::install_sighandler;
|
|
||||||
use crate::webassembly::ErrorKind;
|
|
||||||
|
|
||||||
use crate::nix::sys::signal::{Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV};
|
|
||||||
|
|
||||||
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
|
|
||||||
let prev_jmp_buf = *jmp_buf;
|
|
||||||
|
|
||||||
SIGHANDLER_INIT.call_once(|| {
|
|
||||||
install_sighandler();
|
|
||||||
});
|
|
||||||
|
|
||||||
let signum = setjmp(jmp_buf as *mut ::nix::libc::c_void);
|
|
||||||
if signum != 0 {
|
|
||||||
*jmp_buf = prev_jmp_buf;
|
|
||||||
let addr = CAUGHT_ADDRESS.with(|cell| cell.get());
|
|
||||||
|
|
||||||
let signal = match Signal::from_c_int(signum) {
|
|
||||||
Ok(SIGFPE) => "floating-point exception",
|
|
||||||
Ok(SIGILL) => "illegal instruction",
|
|
||||||
Ok(SIGSEGV) => "segmentation violation",
|
|
||||||
Ok(SIGBUS) => "bus error",
|
|
||||||
Err(_) => "error while getting the Signal",
|
|
||||||
_ => "unkown trapped signal",
|
|
||||||
};
|
|
||||||
Err(ErrorKind::RuntimeError(format!(
|
|
||||||
"trap at {:#x} - {}",
|
|
||||||
addr, signal
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
let ret = $x; // TODO: Switch stack?
|
|
||||||
*jmp_buf = prev_jmp_buf;
|
|
||||||
Ok(ret)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn call_protected<T>(f: impl FnOnce() -> T) -> Result<T, String> {
|
|
||||||
unsafe {
|
|
||||||
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
|
|
||||||
let prev_jmp_buf = *jmp_buf;
|
|
||||||
|
|
||||||
SIGHANDLER_INIT.call_once(|| {
|
|
||||||
install_sighandler();
|
|
||||||
});
|
|
||||||
|
|
||||||
let signum = setjmp(jmp_buf as *mut ::nix::libc::c_void);
|
|
||||||
if signum != 0 {
|
|
||||||
*jmp_buf = prev_jmp_buf;
|
|
||||||
let addr = CAUGHT_ADDRESS.with(|cell| cell.get());
|
|
||||||
|
|
||||||
let signal = match Signal::from_c_int(signum) {
|
|
||||||
Ok(SIGFPE) => "floating-point exception",
|
|
||||||
Ok(SIGILL) => "illegal instruction",
|
|
||||||
Ok(SIGSEGV) => "segmentation violation",
|
|
||||||
Ok(SIGBUS) => "bus error",
|
|
||||||
Err(_) => "error while getting the Signal",
|
|
||||||
_ => "unkown trapped signal",
|
|
||||||
};
|
|
||||||
Err(format!("trap at {:#x} - {}", addr, signal))
|
|
||||||
} else {
|
|
||||||
let ret = f(); // TODO: Switch stack?
|
|
||||||
*jmp_buf = prev_jmp_buf;
|
|
||||||
Ok(ret)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Unwinds to last protected_call.
|
|
||||||
pub unsafe fn do_unwind(signum: i32, siginfo: *mut siginfo_t) -> ! {
|
|
||||||
// Since do_unwind is only expected to get called from WebAssembly code which doesn't hold any host resources (locks etc.)
|
|
||||||
// itself, accessing TLS here is safe. In case any other code calls this, it often indicates a memory safety bug and you should
|
|
||||||
// temporarily disable the signal handlers to debug it.
|
|
||||||
|
|
||||||
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
|
|
||||||
if *jmp_buf == [0; SETJMP_BUFFER_LEN] {
|
|
||||||
::std::process::abort();
|
|
||||||
}
|
|
||||||
// We only target macos at the moment as other ones might not have si_addr field
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
CAUGHT_ADDRESS.with(|cell| cell.set((*siginfo).si_addr as _));
|
|
||||||
|
|
||||||
longjmp(jmp_buf as *mut ::nix::libc::c_void, signum)
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
//! We install signal handlers to handle WebAssembly traps within
|
|
||||||
//! our Rust code. Otherwise we will have errors that stop the Rust process
|
|
||||||
//! such as `process didn't exit successfully: ... (signal: 8, SIGFPE: erroneous arithmetic operation)`
|
|
||||||
//!
|
|
||||||
//! Please read more about this here: https://github.com/CraneStation/wasmtime/issues/15
|
|
||||||
//! This code is inspired by: https://github.com/pepyakin/wasmtime/commit/625a2b6c0815b21996e111da51b9664feb174622
|
|
||||||
use super::recovery;
|
|
||||||
use nix::libc::{c_void, siginfo_t};
|
|
||||||
use nix::sys::signal::{
|
|
||||||
sigaction, SaFlags, SigAction, SigHandler, SigSet, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub unsafe fn install_sighandler() {
|
|
||||||
let sa = SigAction::new(
|
|
||||||
SigHandler::SigAction(signal_trap_handler),
|
|
||||||
SaFlags::SA_ONSTACK,
|
|
||||||
SigSet::empty(),
|
|
||||||
);
|
|
||||||
sigaction(SIGFPE, &sa).unwrap();
|
|
||||||
sigaction(SIGILL, &sa).unwrap();
|
|
||||||
sigaction(SIGSEGV, &sa).unwrap();
|
|
||||||
sigaction(SIGBUS, &sa).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn signal_trap_handler(
|
|
||||||
signum: ::nix::libc::c_int,
|
|
||||||
siginfo: *mut siginfo_t,
|
|
||||||
_ucontext: *mut c_void,
|
|
||||||
) {
|
|
||||||
unsafe {
|
|
||||||
recovery::do_unwind(signum, siginfo);
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user