Stream: git-wasmtime

Topic: wasmtime / issue #2583 Memory never dropped if captured i...


view this post on Zulip Wasmtime GitHub notifications bot (Jan 01 2022 at 17:20):

ZetaNumbers commented on issue #2583:

I tried to replicate this bug on 0.32.0, but it seems to be fixed! I had to update example above, but i am sure logic didn't change:

use wasmtime::*;

struct MyMemory {}
unsafe impl LinearMemory for MyMemory {
    fn byte_size(&self) -> usize {
        0
    }

    fn grow_to(&mut self, _new: usize) -> anyhow::Result<()> {
        anyhow::bail!("cannot grow memory")
    }

    fn as_ptr(&self) -> *mut u8 {
        std::ptr::null_mut()
    }

    fn maximum_byte_size(&self) -> Option<usize> {
        Some(0)
    }
}

impl Drop for MyMemory {
    fn drop(&mut self) {
        println!("Dropped!")
    }
}

struct MyMemoryCreator {}
unsafe impl MemoryCreator for MyMemoryCreator {
    fn new_memory(
        &self,
        _ty: MemoryType,
        _minimum: usize,
        _maximum: Option<usize>,
        _reserved_size_in_bytes: Option<usize>,
        _guard_size_in_bytes: usize,
    ) -> Result<Box<dyn LinearMemory>, String> {
        Ok(Box::new(MyMemory {}))
    }
}

fn main() {
    let mut config = Config::new();
    config.with_host_memory(std::sync::Arc::new(MyMemoryCreator {}));
    let engine = Engine::new(&config).unwrap();
    let mut store = Store::new(&engine, ());
    let mut linker = Linker::<()>::new(&engine);
    let memory_ty = MemoryType::new(1, None);
    let memory = Memory::new(&mut store, memory_ty).unwrap();
    let captured_memory = memory.clone();
    linker
        .func_wrap("", "", move || {
            let _ = captured_memory;
        })
        .unwrap();
}

view this post on Zulip Wasmtime GitHub notifications bot (Jan 04 2022 at 15:17):

alexcrichton commented on issue #2583:

Ah yes indeed, this has been fixed!

view this post on Zulip Wasmtime GitHub notifications bot (Jan 04 2022 at 15:17):

alexcrichton closed issue #2583:

Hi, I'm using wasmtime = 0.21 and run into a bug where the Memory is never dropped if moved inside a closure passed to Linker::func.

Here is a minimal example:

use wasmtime::*;

struct MyMemory {}
unsafe impl LinearMemory for MyMemory {
    fn size(&self) -> u32 {
        0
    }

    fn grow(&self, _delta: u32) -> Option<u32> {
        None
    }

    fn as_ptr(&self) -> *mut u8 {
        std::ptr::null_mut()
    }
}

impl Drop for MyMemory {
    fn drop(&mut self) {
        println!("Dropped!")
    }
}

struct MyMemoryCreator {}
unsafe impl MemoryCreator for MyMemoryCreator {
    fn new_memory(
        &self,
        _ty: MemoryType,
        _reserved_size_in_bytes: Option<u64>,
        _guard_size_in_bytes: u64,
    ) -> Result<Box<dyn LinearMemory>, String> {
        Ok(Box::new(MyMemory {}))
    }
}

fn main() {
    let mut config = Config::new();
    config.with_host_memory(std::sync::Arc::new(MyMemoryCreator {}));
    let engine = Engine::new(&config);
    let store = Store::new(&engine);
    let mut linker = Linker::new(&store);
    let memory_ty = MemoryType::new(Limits::new(1, None));
    let memory = Memory::new(&store, memory_ty);
    let captured_memory = memory.clone();
    linker
        .func("", "", move || {
            let _ = captured_memory;
        })
        .unwrap();
}

MyMemory and MyMemoryCreator are added here only for the purpose of printing out on drop, but the same behaviour is observed with the default Memory.

In this example "Dropped!" is never printed out, but if I comment out let _ = captured_memory; it is. I assume there is somewhere a cycle in reference counting.

I'm also aware that the instance memory can be accessed through the first argument (Caller), but because of some other design decisions I prefer capturing some memories this way. Would this be considered a bug or a Memory should never be captured like this?


Last updated: Dec 23 2024 at 12:05 UTC