Clean up error handling in the C API

This commit is contained in:
Amanieu d'Antras
2021-11-23 16:11:26 +00:00
parent a603c33def
commit e2c6a39d37
7 changed files with 34 additions and 72 deletions

View File

@@ -47,15 +47,14 @@
//! # }
//! ```
use libc::{c_char, c_int};
use libc::c_char;
use std::cell::RefCell;
use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::fmt::Display;
use std::ptr::{self, NonNull};
use std::slice;
thread_local! {
static LAST_ERROR: RefCell<Option<Box<dyn Error>>> = RefCell::new(None);
static LAST_ERROR: RefCell<Option<String>> = RefCell::new(None);
}
/// Rust function to register a new error.
@@ -63,24 +62,23 @@ thread_local! {
/// # Example
///
/// ```rust,no_run
/// # use wasmer::error::{update_last_error, CApiError};
/// # use wasmer::error::update_last_error;
///
/// update_last_error(CApiError {
/// msg: "Hello, World!".to_string(),
/// });
/// update_last_error("Hello, World!");
/// ```
pub fn update_last_error<E: Error + 'static>(err: E) {
pub fn update_last_error<E: Display>(err: E) {
LAST_ERROR.with(|prev| {
*prev.borrow_mut() = Some(Box::new(err));
*prev.borrow_mut() = Some(err.to_string());
});
}
/// Retrieve the most recent error, clearing it in the process.
pub(crate) fn take_last_error() -> Option<Box<dyn Error>> {
pub(crate) fn take_last_error() -> Option<String> {
LAST_ERROR.with(|prev| prev.borrow_mut().take())
}
/// Gets the length in bytes of the last error if any, zero otherwise.
/// Gets the length in bytes of the last error if any, zero otherwise. This
/// includes th NUL terminator byte.
///
/// This can be used to dynamically allocate a buffer with the correct number of
/// bytes needed to store a message.
@@ -89,9 +87,9 @@ pub(crate) fn take_last_error() -> Option<Box<dyn Error>> {
///
/// See this module's documentation to get a complete example.
#[no_mangle]
pub extern "C" fn wasmer_last_error_length() -> c_int {
pub extern "C" fn wasmer_last_error_length() -> usize {
LAST_ERROR.with(|prev| match *prev.borrow() {
Some(ref err) => err.to_string().len() as c_int + 1,
Some(ref err) => err.len() + 1,
None => 0,
})
}
@@ -121,8 +119,8 @@ pub extern "C" fn wasmer_last_error_length() -> c_int {
#[no_mangle]
pub unsafe extern "C" fn wasmer_last_error_message(
buffer: Option<NonNull<c_char>>,
length: c_int,
) -> c_int {
length: usize,
) -> isize {
let buffer = if let Some(buffer_inner) = buffer {
buffer_inner
} else {
@@ -135,8 +133,6 @@ pub unsafe extern "C" fn wasmer_last_error_message(
None => return 0,
};
let length = length as usize;
if error_message.len() >= length {
// buffer is too small to hold the error message
return -1;
@@ -154,20 +150,5 @@ pub unsafe extern "C" fn wasmer_last_error_message(
// accidentally read into garbage.
buffer[error_message.len()] = 0;
error_message.len() as c_int + 1
error_message.len() as isize + 1
}
/// Rust type to represent a C API error.
#[derive(Debug)]
pub struct CApiError {
/// The error message.
pub msg: String,
}
impl Display for CApiError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", &self.msg)
}
}
impl Error for CApiError {}