mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 22:25:40 +00:00
Add notes about async signal safety
This commit is contained in:
parent
5de9f0f7b4
commit
a316253b94
@ -1,4 +1,8 @@
|
|||||||
//! When a WebAssembly module triggers any traps, we perform recovery here.
|
//! 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 std::cell::UnsafeCell;
|
use std::cell::UnsafeCell;
|
||||||
|
|
||||||
@ -13,8 +17,8 @@ thread_local! {
|
|||||||
static SETJMP_BUFFER: UnsafeCell<[::nix::libc::c_int; SETJMP_BUFFER_LEN]> = UnsafeCell::new([0; SETJMP_BUFFER_LEN]);
|
static SETJMP_BUFFER: UnsafeCell<[::nix::libc::c_int; SETJMP_BUFFER_LEN]> = UnsafeCell::new([0; SETJMP_BUFFER_LEN]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls a function with longjmp receiver installed. The function must be compiled from WebAssembly;
|
/// Calls a WebAssembly function with longjmp receiver installed. If a non-WebAssembly function is passed in,
|
||||||
/// Otherwise, the behavior is undefined.
|
/// the behavior of protected_call is undefined.
|
||||||
pub unsafe fn protected_call<T, R>(f: fn(T) -> R, p: T) -> Result<R, i32> {
|
pub unsafe fn protected_call<T, R>(f: fn(T) -> R, p: T) -> Result<R, i32> {
|
||||||
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
|
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
|
||||||
let prev_jmp_buf = *jmp_buf;
|
let prev_jmp_buf = *jmp_buf;
|
||||||
@ -24,7 +28,7 @@ pub unsafe fn protected_call<T, R>(f: fn(T) -> R, p: T) -> Result<R, i32> {
|
|||||||
*jmp_buf = prev_jmp_buf;
|
*jmp_buf = prev_jmp_buf;
|
||||||
Err(signum)
|
Err(signum)
|
||||||
} else {
|
} else {
|
||||||
let ret = f(p);
|
let ret = f(p); // TODO: Switch stack?
|
||||||
*jmp_buf = prev_jmp_buf;
|
*jmp_buf = prev_jmp_buf;
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
@ -32,6 +36,10 @@ pub unsafe fn protected_call<T, R>(f: fn(T) -> R, p: T) -> Result<R, i32> {
|
|||||||
|
|
||||||
/// Unwinds to last protected_call.
|
/// Unwinds to last protected_call.
|
||||||
pub unsafe fn do_unwind(signum: i32) -> ! {
|
pub unsafe fn do_unwind(signum: i32) -> ! {
|
||||||
|
// 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());
|
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
|
||||||
if *jmp_buf == [0; SETJMP_BUFFER_LEN] {
|
if *jmp_buf == [0; SETJMP_BUFFER_LEN] {
|
||||||
::std::process::abort();
|
::std::process::abort();
|
||||||
|
Loading…
Reference in New Issue
Block a user