Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add C API for epoch_deadline_callback and wasmtime_error_t creation #6359

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions crates/c-api/include/wasmtime/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ extern "C" {
*/
typedef struct wasmtime_error wasmtime_error_t;

/**
* \brief Creates a new error with the provided message.
*/
WASM_API_EXTERN wasmtime_error_t *wasmtime_error_new(const char*);

/**
* \brief Deletes an error.
*/
Expand Down
21 changes: 18 additions & 3 deletions crates/c-api/include/wasmtime/store.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,15 +206,30 @@ WASM_API_EXTERN wasmtime_error_t *wasmtime_context_set_wasi(wasmtime_context_t *

/**
* \brief Configures the relative deadline at which point WebAssembly code will
* trap.
* trap or invoke the callback function.
*
* This function configures the store-local epoch deadline after which point
* WebAssembly code will trap.
* WebAssembly code will trap or invoke the callback function.
*
* See also #wasmtime_config_epoch_interruption_set.
* See also #wasmtime_config_epoch_interruption_set and
* #wasmtime_store_epoch_deadline_callback.
*/
WASM_API_EXTERN void wasmtime_context_set_epoch_deadline(wasmtime_context_t *context, uint64_t ticks_beyond_current);

/**
* \brief Configures epoch deadline callback to C function.
*
* This function configures a store-local callback function that will be
* called when the running WebAssembly function has exceeded its epoch
* deadline. That function can return a #wasmtime_error_t to terminate
* the function, or set the delta argument and return NULL to update the
* epoch deadline and resume function execution.
*
* See also #wasmtime_config_epoch_interruption_set and
* #wasmtime_context_set_epoch_deadline.
*/
WASM_API_EXTERN void wasmtime_store_epoch_deadline_callback(wasmtime_store_t *store, wasmtime_error_t* (*func)(wasmtime_context_t*, void*, uint64_t*), void *data);

#ifdef __cplusplus
} // extern "C"
#endif
Expand Down
15 changes: 15 additions & 0 deletions crates/c-api/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ impl From<Error> for wasmtime_error_t {
}
}

impl Into<Error> for wasmtime_error_t {
fn into(self) -> Error {
self.error
}
}

#[no_mangle]
pub extern "C" fn wasmtime_error_new(
msg: *const std::ffi::c_char,
) -> Option<Box<wasmtime_error_t>> {
Some(Box::new(wasmtime_error_t::from(anyhow!("{:?}", unsafe {
std::ffi::CStr::from_ptr(msg)
}))))
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think instead of :? this should use .to_str() on the pointer received to avoid Rust-level string escaping which shows up in the debug representation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.to_str() leaves me with the potential to get a Utf8Error instead of a &str. I was not sure what the preferred way to deal with such bad input would be, but based on what I see in crates/c-api/src/trap.rs, I think I will go with String::from_utf8_lossy(). Sound good?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think the _lossy variant is fine. That's a reality of working with cross-language FFI here but in the context of "just an error message" the lossy variant should be fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, revised.


pub(crate) fn handle_result<T>(
result: Result<T>,
ok: impl FnOnce(T),
Expand Down
42 changes: 42 additions & 0 deletions crates/c-api/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,48 @@ pub extern "C" fn wasmtime_store_new(
})
}

// Internal structure to add Send/Sync to the c_void member.
#[derive(Debug)]
pub struct CallbackDataPtr {
pub ptr: *mut c_void,
}

impl CallbackDataPtr {
fn as_mut_ptr(&self) -> *mut c_void {
self.ptr
}
}

unsafe impl Send for CallbackDataPtr {}
unsafe impl Sync for CallbackDataPtr {}

#[no_mangle]
pub extern "C" fn wasmtime_store_epoch_deadline_callback(
store: &mut wasmtime_store_t,
func: extern "C" fn(
CStoreContextMut<'_>,
*mut c_void,
*mut u64,
) -> Option<Box<wasmtime_error_t>>,
data: *mut c_void,
) {
let sendable = CallbackDataPtr { ptr: data };
store.store.epoch_deadline_callback(move |mut store_ctx| {
let mut delta: u64 = 0;
let result = (func)(
store_ctx.as_context_mut(),
sendable.as_mut_ptr(),
&mut delta as *mut u64,
);
match result {
Some(err) => Err(wasmtime::Error::from(<wasmtime_error_t as Into<
anyhow::Error,
>>::into(*err))),
None => Ok(delta),
}
});
}

#[no_mangle]
pub extern "C" fn wasmtime_store_context(store: &mut wasmtime_store_t) -> CStoreContextMut<'_> {
store.store.as_context_mut()
Expand Down