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

wasmtime: Make StoreContextMut accessible in the epoch deadline callback #6075

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
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
19 changes: 14 additions & 5 deletions crates/wasmtime/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,11 +425,13 @@ enum OutOfGas {

/// What to do when the engine epoch reaches the deadline for a Store
/// during execution of a function using that store.
#[derive(Default)]
enum EpochDeadline<T> {
/// Return early with a trap.
#[default]
Trap,
/// Call a custom deadline handler.
Callback(Box<dyn FnMut(&mut T) -> Result<u64> + Send + Sync>),
Callback(Box<dyn FnMut(StoreContextMut<T>) -> Result<u64> + Send + Sync>),
/// Extend the deadline by the specified number of ticks after
/// yielding to the async executor loop.
#[cfg(feature = "async")]
Expand Down Expand Up @@ -932,7 +934,7 @@ impl<T> Store<T> {
/// for an introduction to epoch-based interruption.
pub fn epoch_deadline_callback(
&mut self,
callback: impl FnMut(&mut T) -> Result<u64> + Send + Sync + 'static,
callback: impl FnMut(StoreContextMut<T>) -> Result<u64> + Send + Sync + 'static,
) {
self.inner.epoch_deadline_callback(Box::new(callback));
}
Expand Down Expand Up @@ -1975,10 +1977,13 @@ unsafe impl<T> wasmtime_runtime::Store for StoreInner<T> {
}

fn new_epoch(&mut self) -> Result<u64, anyhow::Error> {
return match &mut self.epoch_deadline_behavior {
// Temporarily take the configured behavior to avoid mutably borrowing
// multiple times.
let mut behavior = std::mem::take(&mut self.epoch_deadline_behavior);
let delta_result = match &mut behavior {
EpochDeadline::Trap => Err(Trap::Interrupt.into()),
EpochDeadline::Callback(callback) => {
let delta = callback(&mut self.data)?;
let delta = callback((&mut *self).as_context_mut())?;
// Set a new deadline and return the new epoch deadline so
// the Wasm code doesn't have to reload it.
self.set_epoch_deadline(delta);
Expand All @@ -1998,6 +2003,10 @@ unsafe impl<T> wasmtime_runtime::Store for StoreInner<T> {
Ok(self.get_epoch_deadline())
}
};

// Put back the original behavior which was replaced by `take`.
self.epoch_deadline_behavior = behavior;
delta_result
}
}

Expand All @@ -2022,7 +2031,7 @@ impl<T> StoreInner<T> {

fn epoch_deadline_callback(
&mut self,
callback: Box<dyn FnMut(&mut T) -> Result<u64> + Send + Sync>,
callback: Box<dyn FnMut(StoreContextMut<T>) -> Result<u64> + Send + Sync>,
) {
self.epoch_deadline_behavior = EpochDeadline::Callback(callback);
}
Expand Down
5 changes: 3 additions & 2 deletions tests/all/epoch_interruption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fn make_env<T>(engine: &Engine) -> Linker<T> {

enum InterruptMode {
Trap,
Callback(fn(&mut usize) -> Result<u64>),
Callback(fn(StoreContextMut<usize>) -> Result<u64>),
Yield(u64),
}

Expand Down Expand Up @@ -334,7 +334,8 @@ async fn epoch_callback_continue() {
(func $subfunc))
",
1,
InterruptMode::Callback(|s| {
InterruptMode::Callback(|mut cx| {
let s = cx.data_mut();
*s += 1;
Ok(1)
}),
Expand Down