* Revamp memory management of `InstanceHandle` This commit fixes a known but in Wasmtime where an instance could still be used after it was freed. Unfortunately the fix here is a bit of a hammer, but it's the best that we can do for now. The changes made in this commit are: * A `Store` now stores all `InstanceHandle` objects it ever creates. This keeps all instances alive unconditionally (along with all host functions and such) until the `Store` is itself dropped. Note that a `Store` is reference counted so basically everything has to be dropped to drop anything, there's no longer any partial deallocation of instances. * The `InstanceHandle` type's own reference counting has been removed. This is largely redundant with what's already happening in `Store`, so there's no need to manage two reference counts. * Each `InstanceHandle` no longer tracks its dependencies in terms of instance handles. This set was actually inaccurate due to dynamic updates to tables and such, so we needed to revamp it anyway. * Initialization of an `InstanceHandle` is now deferred until after `InstanceHandle::new`. This allows storing the `InstanceHandle` before side-effectful initialization, such as copying element segments or running the start function, to ensure that regardless of the result of instantiation the underlying `InstanceHandle` is still available to persist in storage. Overall this should fix a known possible way to safely segfault Wasmtime today (yay!) and it should also fix some flaikness I've seen on CI. Turns out one of the spec tests (bulk-memory-operations/partial-init-table-segment.wast) exercises this functionality and we were hitting sporating use-after-free, but only on Windows. * Shuffle some APIs around * Comment weak cycle
36 lines
1.1 KiB
Rust
36 lines
1.1 KiB
Rust
use super::create_handle::create_handle;
|
|
use crate::trampoline::StoreInstanceHandle;
|
|
use crate::Store;
|
|
use crate::{TableType, ValType};
|
|
use anyhow::{bail, Result};
|
|
use wasmtime_environ::entity::PrimaryMap;
|
|
use wasmtime_environ::{wasm, EntityIndex, Module};
|
|
|
|
pub fn create_handle_with_table(store: &Store, table: &TableType) -> Result<StoreInstanceHandle> {
|
|
let mut module = Module::new();
|
|
|
|
let table = wasm::Table {
|
|
minimum: table.limits().min(),
|
|
maximum: table.limits().max(),
|
|
ty: match table.element() {
|
|
ValType::FuncRef => wasm::TableElementType::Func,
|
|
_ => bail!("cannot support {:?} as a table element", table.element()),
|
|
},
|
|
};
|
|
let tunable = Default::default();
|
|
|
|
let table_plan = wasmtime_environ::TablePlan::for_table(table, &tunable);
|
|
let table_id = module.local.table_plans.push(table_plan);
|
|
module
|
|
.exports
|
|
.insert("table".to_string(), EntityIndex::Table(table_id));
|
|
|
|
create_handle(
|
|
module,
|
|
store,
|
|
PrimaryMap::new(),
|
|
Default::default(),
|
|
Box::new(()),
|
|
)
|
|
}
|