Skip to content

Commit

Permalink
Fix borrow scope for store in WrappedCallable impl for WasmtimeFn.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
peterhuene authored and sunfishcode committed Sep 26, 2019
1 parent a666e14 commit 4288f33
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 4 deletions.
1 change: 1 addition & 0 deletions test-all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ banner "Rust unit tests"
#RUST_BACKTRACE=1 cargo test --all
RUST_BACKTRACE=1 cargo test \
--package wasmtime \
--package wasmtime-api \
--package wasmtime-wasi \
--package wasmtime-wast \
--package wasmtime-debug \
Expand Down
8 changes: 4 additions & 4 deletions wasmtime-api/src/callable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@ impl WrappedCallable for WasmtimeFn {
_ => 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 mut values_vec: Vec<u64> = vec![0; max(params.len(), results.len())];

Expand All @@ -78,7 +75,10 @@ impl WrappedCallable for WasmtimeFn {
}

// Get the trampoline to call for this function.
let exec_code_buf = context
let exec_code_buf = self
.store
.borrow_mut()
.context()
.compiler()
.get_published_trampoline(body, &signature, value_size)
.map_err(|_| HostRef::new(Trap::fake()))?; //was ActionError::Setup)?;
Expand Down
69 changes: 69 additions & 0 deletions wasmtime-api/tests/import_calling_export.rs
Original file line number Diff line number Diff line change
@@ -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");
}
Binary file added wasmtime-api/tests/import_calling_export.wasm
Binary file not shown.
8 changes: 8 additions & 0 deletions wasmtime-api/tests/import_calling_export.wat
Original file line number Diff line number Diff line change
@@ -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))
)

0 comments on commit 4288f33

Please sign in to comment.