Skip to content

Commit 965b4cb

Browse files
authored
Fix callbacks accessing memory when main exits (#923)
The scheduler panics when trying to access the memory of an applet when no threads are running. This only affects wasm and not pulley.
1 parent e59a9c3 commit 965b4cb

File tree

5 files changed

+33
-15
lines changed

5 files changed

+33
-15
lines changed

crates/interpreter/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## 0.4.1-git
44

5+
### Minor
6+
7+
- Add `Store::memory()` to access the memory of a given instance
8+
59
### Patch
610

711
- Update dependencies

crates/interpreter/src/exec.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,12 @@ impl<'m> Store<'m> {
304304
pub fn last_call(&mut self) -> Option<Call<'_, 'm>> {
305305
if self.threads.is_empty() { None } else { Some(Call { store: self }) }
306306
}
307+
308+
/// Returns the memory of the given instance.
309+
pub fn memory(&mut self, inst: InstId) -> Result<&mut [u8], Error> {
310+
check(self.id == inst.store_id)?;
311+
Ok(self.mem(inst.inst_id, 0).data)
312+
}
307313
}
308314

309315
impl<'a, 'm> Call<'a, 'm> {

crates/scheduler/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Patch
66

7+
- Fix callbacks accessing memory when no threads are running
78
- Update dependencies
89

910
## 0.5.0

crates/scheduler/src/applet.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use crate::event::{Handler, Key};
3232

3333
pub mod store;
3434

35+
#[allow(clippy::large_enum_variant)]
3536
pub enum Slot<B: Board> {
3637
#[cfg(any(feature = "pulley", feature = "wasm"))]
3738
Empty,

crates/scheduler/src/applet/store/wasm.rs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,33 +26,40 @@ use super::StoreApi;
2626
use crate::Trap;
2727

2828
#[derive(Debug, Default)]
29-
pub struct Store(InterpreterStore<'static>);
29+
pub struct Store {
30+
inst: Option<InstId>,
31+
store: InterpreterStore<'static>,
32+
}
3033

3134
impl Store {
3235
pub fn instantiate(
3336
&mut self, module: Module<'static>, memory: &'static mut [u8],
3437
) -> Result<InstId, Error> {
35-
self.0.instantiate(module, memory)
38+
// We assume a single module per applet.
39+
assert!(self.inst.is_none());
40+
let inst = self.store.instantiate(module, memory)?;
41+
self.inst = Some(inst);
42+
Ok(inst)
3643
}
3744

3845
pub fn link_func(
3946
&mut self, module: &'static str, name: &'static str, params: usize, results: usize,
4047
) -> Result<(), Error> {
41-
self.0.link_func(module, name, params, results)
48+
self.store.link_func(module, name, params, results)
4249
}
4350

4451
pub fn link_func_default(&mut self, module: &'static str) -> Result<(), Error> {
45-
self.0.link_func_default(module)
52+
self.store.link_func_default(module)
4653
}
4754

4855
pub fn invoke<'a>(
4956
&'a mut self, inst: InstId, name: &str, args: Vec<Val>,
5057
) -> Result<RunResult<'a, 'static>, Error> {
51-
self.0.invoke(inst, name, args)
58+
self.store.invoke(inst, name, args)
5259
}
5360

5461
pub fn last_call(&mut self) -> Option<Call<'_, 'static>> {
55-
self.0.last_call()
62+
self.store.last_call()
5663
}
5764
}
5865

@@ -61,26 +68,25 @@ impl StoreApi for Store {
6168
= Memory<'a>
6269
where Self: 'a;
6370

64-
fn memory(&mut self) -> Memory<'_> {
65-
Memory::new(&mut self.0)
71+
fn memory<'a>(&'a mut self) -> Memory<'a> {
72+
let inst = self.inst.unwrap();
73+
let store = self as *mut Store;
74+
let memory = SliceCell::new(self.store.memory(inst).unwrap());
75+
Memory { store, memory }
6676
}
6777
}
6878

6979
pub struct Memory<'a> {
70-
store: *mut InterpreterStore<'static>,
80+
store: *mut Store,
7181
memory: SliceCell<'a, u8>,
7282
}
7383

7484
impl<'a> Memory<'a> {
75-
fn new(store: &'a mut InterpreterStore<'static>) -> Self {
76-
Self { store, memory: SliceCell::new(store.last_call().unwrap().mem()) }
77-
}
78-
79-
fn with_store<T>(&mut self, f: impl FnOnce(&mut InterpreterStore<'static>) -> T) -> T {
85+
fn with_store<T>(&mut self, f: impl FnOnce(&mut Store) -> T) -> T {
8086
self.memory.reset(); // only to free the internal state early
8187
let store = unsafe { &mut *self.store };
8288
let result = f(store);
83-
*self = Memory::new(store);
89+
*self = store.memory();
8490
result
8591
}
8692
}

0 commit comments

Comments
 (0)