Fix borrow scope for store in WrappedCallable impl for WasmtimeFn.
This PR fixes the borrow scope of store in the `WrappedCallable` impl of `WasmTimeFn` such that it does not remain borrowed across the call to `wasmtime_call_trampoline`. By limiting the scope of the borrow, the implementation can be reentered if an exported function calls an imported function, which in turn calls another exported function. Fixes #365.
This commit is contained in:
@@ -52,6 +52,7 @@ banner "Rust unit tests"
|
|||||||
#RUST_BACKTRACE=1 cargo test --all
|
#RUST_BACKTRACE=1 cargo test --all
|
||||||
RUST_BACKTRACE=1 cargo test \
|
RUST_BACKTRACE=1 cargo test \
|
||||||
--package wasmtime \
|
--package wasmtime \
|
||||||
|
--package wasmtime-api \
|
||||||
--package wasmtime-wasi \
|
--package wasmtime-wasi \
|
||||||
--package wasmtime-wast \
|
--package wasmtime-wast \
|
||||||
--package wasmtime-debug \
|
--package wasmtime-debug \
|
||||||
|
|||||||
@@ -56,9 +56,6 @@ impl WrappedCallable for WasmtimeFn {
|
|||||||
_ => panic!("unexpected export type in Callable"),
|
_ => panic!("unexpected export type in Callable"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut store = self.store.borrow_mut();
|
|
||||||
|
|
||||||
let context = store.context();
|
|
||||||
let value_size = mem::size_of::<u64>();
|
let value_size = mem::size_of::<u64>();
|
||||||
let mut values_vec: Vec<u64> = vec![0; max(params.len(), results.len())];
|
let mut values_vec: Vec<u64> = vec![0; max(params.len(), results.len())];
|
||||||
|
|
||||||
@@ -78,7 +75,10 @@ impl WrappedCallable for WasmtimeFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the trampoline to call for this function.
|
// Get the trampoline to call for this function.
|
||||||
let exec_code_buf = context
|
let exec_code_buf = self
|
||||||
|
.store
|
||||||
|
.borrow_mut()
|
||||||
|
.context()
|
||||||
.compiler()
|
.compiler()
|
||||||
.get_published_trampoline(body, &signature, value_size)
|
.get_published_trampoline(body, &signature, value_size)
|
||||||
.map_err(|_| HostRef::new(Trap::fake()))?; //was ActionError::Setup)?;
|
.map_err(|_| HostRef::new(Trap::fake()))?; //was ActionError::Setup)?;
|
||||||
|
|||||||
69
wasmtime-api/tests/import_calling_export.rs
Normal file
69
wasmtime-api/tests/import_calling_export.rs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
use std::cell::{Ref, RefCell};
|
||||||
|
use std::fs::read;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use wasmtime_api::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_import_calling_export() {
|
||||||
|
struct Callback {
|
||||||
|
pub other: RefCell<Option<HostRef<Func>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Callable for Callback {
|
||||||
|
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), HostRef<Trap>> {
|
||||||
|
self.other
|
||||||
|
.borrow()
|
||||||
|
.as_ref()
|
||||||
|
.expect("expected a function ref")
|
||||||
|
.borrow()
|
||||||
|
.call(&[])
|
||||||
|
.expect("expected function not to trap");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let engine = HostRef::new(Engine::new(Config::default()));
|
||||||
|
let store = HostRef::new(Store::new(engine));
|
||||||
|
let module = HostRef::new(
|
||||||
|
Module::new(
|
||||||
|
store.clone(),
|
||||||
|
&read("tests/import_calling_export.wasm").expect("failed to read wasm file"),
|
||||||
|
)
|
||||||
|
.expect("failed to create module"),
|
||||||
|
);
|
||||||
|
|
||||||
|
let callback = Rc::new(Callback {
|
||||||
|
other: RefCell::new(None),
|
||||||
|
});
|
||||||
|
|
||||||
|
let callback_func = HostRef::new(Func::new(
|
||||||
|
store.clone(),
|
||||||
|
FuncType::new(Box::new([]), Box::new([])),
|
||||||
|
callback.clone(),
|
||||||
|
));
|
||||||
|
|
||||||
|
let imports = vec![callback_func.into()];
|
||||||
|
let instance = HostRef::new(
|
||||||
|
Instance::new(store.clone(), module, imports.as_slice())
|
||||||
|
.expect("failed to instantiate module"),
|
||||||
|
);
|
||||||
|
|
||||||
|
let exports = Ref::map(instance.borrow(), |instance| instance.exports());
|
||||||
|
assert!(!exports.is_empty());
|
||||||
|
|
||||||
|
let run_func = exports[0]
|
||||||
|
.func()
|
||||||
|
.expect("expected a run func in the module");
|
||||||
|
|
||||||
|
*callback.other.borrow_mut() = Some(
|
||||||
|
exports[1]
|
||||||
|
.func()
|
||||||
|
.expect("expected an other func in the module")
|
||||||
|
.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
run_func
|
||||||
|
.borrow()
|
||||||
|
.call(&[])
|
||||||
|
.expect("expected function not to trap");
|
||||||
|
}
|
||||||
BIN
wasmtime-api/tests/import_calling_export.wasm
Normal file
BIN
wasmtime-api/tests/import_calling_export.wasm
Normal file
Binary file not shown.
8
wasmtime-api/tests/import_calling_export.wat
Normal file
8
wasmtime-api/tests/import_calling_export.wat
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
(module
|
||||||
|
(type $t0 (func))
|
||||||
|
(import "" "imp" (func $.imp (type $t0)))
|
||||||
|
(func $run call $.imp)
|
||||||
|
(func $other)
|
||||||
|
(export "run" (func $run))
|
||||||
|
(export "other" (func $other))
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user