Skip to content

Commit 640710c

Browse files
committed
Use more solid Send and Sync bounds
1 parent f6c9c46 commit 640710c

File tree

6 files changed

+65
-24
lines changed

6 files changed

+65
-24
lines changed

packages/std/src/testing/mock.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,12 @@ impl Default for WasmQuerier {
606606
};
607607
SystemResult::Err(err)
608608
});
609+
610+
// check that this handler is Send + Sync
611+
// see `cosmwasm_vm::MockQuerier`'s `Send` and `Sync` impls for more details
612+
fn assert_send_sync(_: &(impl Send + Sync)) {}
613+
assert_send_sync(&handler);
614+
609615
Self::new(handler)
610616
}
611617
}

packages/vm/src/backend.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub struct Backend<A: BackendApi, S: Storage, Q: Querier> {
8585
}
8686

8787
/// Access to the VM's backend storage, i.e. the chain
88-
pub trait Storage {
88+
pub trait Storage: Send + Sync {
8989
/// Returns Err on error.
9090
/// Returns Ok(None) when key does not exist.
9191
/// Returns Ok(Some(Vec<u8>)) when key exists.
@@ -171,7 +171,7 @@ pub trait BackendApi: Clone + Send {
171171
fn addr_humanize(&self, canonical: &[u8]) -> BackendResult<String>;
172172
}
173173

174-
pub trait Querier {
174+
pub trait Querier: Send + Sync {
175175
/// This is all that must be implemented for the Querier.
176176
/// This allows us to pass through binary queries from one level to another without
177177
/// knowing the custom format, or we can decode it, with the knowledge of the allowed

packages/vm/src/environment.rs

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
//! Internal details to be used by instance.rs only
22
use std::borrow::BorrowMut;
3-
use std::cell::RefCell;
43
use std::marker::PhantomData;
54
use std::ptr::NonNull;
6-
use std::rc::Rc;
7-
use std::sync::{Arc, RwLock};
5+
use std::sync::{Arc, Mutex, RwLock};
86

97
use derivative::Derivative;
108
use wasmer::{AsStoreMut, Instance as WasmerInstance, Memory, MemoryView, Value};
@@ -106,7 +104,7 @@ pub struct DebugInfo<'a> {
106104
// /- BEGIN TRAIT END TRAIT \
107105
// | |
108106
// v v
109-
pub type DebugHandlerFn = dyn for<'a, 'b> FnMut(/* msg */ &'a str, DebugInfo<'b>);
107+
pub type DebugHandlerFn = dyn for<'a, 'b> FnMut(/* msg */ &'a str, DebugInfo<'b>) + Send + Sync;
110108

111109
/// A environment that provides access to the ContextData.
112110
/// The environment is clonable but clones access the same underlying data.
@@ -117,10 +115,6 @@ pub struct Environment<A, S, Q> {
117115
data: Arc<RwLock<ContextData<S, Q>>>,
118116
}
119117

120-
unsafe impl<A: BackendApi, S: Storage, Q: Querier> Send for Environment<A, S, Q> {}
121-
122-
unsafe impl<A: BackendApi, S: Storage, Q: Querier> Sync for Environment<A, S, Q> {}
123-
124118
impl<A: BackendApi, S: Storage, Q: Querier> Clone for Environment<A, S, Q> {
125119
fn clone(&self) -> Self {
126120
Environment {
@@ -142,15 +136,15 @@ impl<A: BackendApi, S: Storage, Q: Querier> Environment<A, S, Q> {
142136
}
143137
}
144138

145-
pub fn set_debug_handler(&self, debug_handler: Option<Rc<RefCell<DebugHandlerFn>>>) {
139+
pub fn set_debug_handler(&self, debug_handler: Option<Arc<Mutex<DebugHandlerFn>>>) {
146140
self.with_context_data_mut(|context_data| {
147141
context_data.debug_handler = debug_handler;
148142
})
149143
}
150144

151-
pub fn debug_handler(&self) -> Option<Rc<RefCell<DebugHandlerFn>>> {
145+
pub fn debug_handler(&self) -> Option<Arc<Mutex<DebugHandlerFn>>> {
152146
self.with_context_data(|context_data| {
153-
// This clone here requires us to wrap the function in Rc instead of Box
147+
// This clone here requires us to wrap the function in Arc instead of Box
154148
context_data.debug_handler.clone()
155149
})
156150
}
@@ -282,7 +276,7 @@ impl<A: BackendApi, S: Storage, Q: Querier> Environment<A, S, Q> {
282276
/// Creates a back reference from a contact to its partent instance
283277
pub fn set_wasmer_instance(&self, wasmer_instance: Option<NonNull<WasmerInstance>>) {
284278
self.with_context_data_mut(|context_data| {
285-
context_data.wasmer_instance = wasmer_instance;
279+
context_data.wasmer_instance = wasmer_instance.map(WasmerRef);
286280
});
287281
}
288282

@@ -399,9 +393,42 @@ pub struct ContextData<S, Q> {
399393
storage_readonly: bool,
400394
call_depth: usize,
401395
querier: Option<Q>,
402-
debug_handler: Option<Rc<RefCell<DebugHandlerFn>>>,
396+
debug_handler: Option<Arc<Mutex<DebugHandlerFn>>>,
403397
/// A non-owning link to the wasmer instance
404-
wasmer_instance: Option<NonNull<WasmerInstance>>,
398+
wasmer_instance: Option<WasmerRef>,
399+
}
400+
401+
/// A non-owning link to the wasmer instance
402+
///
403+
/// This wrapper type allows us to implement `Send` and `Sync`.
404+
#[derive(Clone, Copy)]
405+
struct WasmerRef(NonNull<WasmerInstance>);
406+
407+
impl WasmerRef {
408+
pub unsafe fn as_ref<'a>(&self) -> &'a WasmerInstance {
409+
self.0.as_ref()
410+
}
411+
}
412+
413+
//
414+
unsafe impl Send for WasmerRef {}
415+
unsafe impl Sync for WasmerRef {}
416+
417+
/// TODO: SAFETY
418+
// unsafe impl<S: Sync, Q: Sync> Sync for ContextData<S, Q> {}
419+
420+
/// Implementing `Send` is safe here as long as `WasmerInstance` is Send.
421+
/// This is guaranteed by the function definition below.
422+
// unsafe impl<S: Send, Q: Send> Send for ContextData<S, Q> {}
423+
424+
#[allow(dead_code)]
425+
fn assert_is_send<T: Send>(_: PhantomData<T>) {}
426+
#[allow(dead_code)]
427+
fn assert_is_sync<T: Sync>(_: PhantomData<T>) {}
428+
#[allow(dead_code)]
429+
fn assert_wasmer_instance() {
430+
assert_is_send(PhantomData::<WasmerInstance>);
431+
assert_is_sync(PhantomData::<WasmerInstance>);
405432
}
406433

407434
impl<S: Storage, Q: Querier> ContextData<S, Q> {

packages/vm/src/imports.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ pub fn do_debug<A: BackendApi + 'static, S: Storage + 'static, Q: Querier + 'sta
436436
let message_data = read_region(&data.memory(&store), message_ptr, MAX_LENGTH_DEBUG)?;
437437
let msg = String::from_utf8_lossy(&message_data);
438438
let gas_remaining = data.get_gas_left(&mut store);
439-
debug_handler.borrow_mut()(
439+
(debug_handler.lock().unwrap())(
440440
&msg,
441441
DebugInfo {
442442
gas_remaining,

packages/vm/src/instance.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
use std::cell::RefCell;
21
use std::collections::{HashMap, HashSet};
32
use std::ptr::NonNull;
4-
use std::rc::Rc;
5-
use std::sync::Mutex;
3+
use std::sync::{Arc, Mutex};
64

75
use wasmer::{
86
Exports, Function, FunctionEnv, Imports, Instance as WasmerInstance, Module, Store, Value,
@@ -307,11 +305,11 @@ where
307305

308306
pub fn set_debug_handler<H>(&mut self, debug_handler: H)
309307
where
310-
H: for<'a, 'b> FnMut(/* msg */ &'a str, DebugInfo<'b>) + 'static,
308+
H: for<'a, 'b> FnMut(/* msg */ &'a str, DebugInfo<'b>) + 'static + Send + Sync,
311309
{
312310
self.fe
313311
.as_ref(&self.store)
314-
.set_debug_handler(Some(Rc::new(RefCell::new(debug_handler))));
312+
.set_debug_handler(Some(Arc::new(Mutex::new(debug_handler))));
315313
}
316314

317315
pub fn unset_debug_handler(&mut self) {

packages/vm/src/testing/querier.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ pub struct MockQuerier<C: CustomQuery + DeserializeOwned = Empty> {
1919
querier: StdMockQuerier<C>,
2020
}
2121

22+
// SAFETY: The only thing in `MockQuerier` that is not `Send + Sync` are
23+
// the custom handler and wasm handler.
24+
// The default custom handler does not use the reference it gets,
25+
// so it should be safe to assume it is `Send + Sync`.
26+
// When setting these in `update_wasm` or `with_custom_handler`, we require them to be `Send + Sync`.
27+
unsafe impl<C: CustomQuery + DeserializeOwned> Send for MockQuerier<C> {}
28+
unsafe impl<C: CustomQuery + DeserializeOwned> Sync for MockQuerier<C> {}
29+
2230
impl<C: CustomQuery + DeserializeOwned> MockQuerier<C> {
2331
pub fn new(balances: &[(&str, &[Coin])]) -> Self {
2432
MockQuerier {
@@ -47,14 +55,16 @@ impl<C: CustomQuery + DeserializeOwned> MockQuerier<C> {
4755

4856
pub fn update_wasm<WH: 'static>(&mut self, handler: WH)
4957
where
50-
WH: Fn(&cosmwasm_std::WasmQuery) -> cosmwasm_std::QuerierResult,
58+
WH: Fn(&cosmwasm_std::WasmQuery) -> cosmwasm_std::QuerierResult + Sync + Send,
59+
// see above for Sync + Send bound explanation
5160
{
5261
self.querier.update_wasm(handler)
5362
}
5463

5564
pub fn with_custom_handler<CH: 'static>(mut self, handler: CH) -> Self
5665
where
57-
CH: Fn(&C) -> MockQuerierCustomHandlerResult,
66+
CH: Fn(&C) -> MockQuerierCustomHandlerResult + Sync + Send,
67+
// see above for Sync + Send bound explanation
5868
{
5969
self.querier = self.querier.with_custom_handler(handler);
6070
self

0 commit comments

Comments
 (0)