Stream: wasmtime

Topic: ResourceTable with lifetime field.


view this post on Zulip Bryton (Jul 05 2024 at 04:11):

Hello,

If it is possible to push a struct with reference filed to a ResourceTable? I failed to try to impl the Trait method that's declared by wasmtime::component::bindgen!(...).

// the data struct I want to push into ResourceTable, it has a  reference typed field `map`
pub struct MapKeyIter<'a> {
    map: &'a MapHandle,
    prev: Option<Vec<u8>>,
    next: Vec<u8>,
}

// bindgen!() generates Trait definition

            pub trait HostMapKeyIter {
                fn next(
                    &mut self,
                    self_: wasmtime::component::Resource<MapKeyIter>,
                ) -> wasmtime::Result<Result<Option<Value>, ()>>;
                fn drop(
                    &mut self,
                    rep: wasmtime::component::Resource<MapKeyIter>,
                ) -> wasmtime::Result<()>;
            }


// My impl code of `HostMapKeyIter` trait

impl<'a, State> ebpf::HostMapKeyIter for BpfCtx<'a, State> {
    fn next(
        &mut self,
        self_: wasmtime::component::Resource<libbpf_rs::MapKeyIter>,
    ) -> Result<Result<Option<Vec<u8>>, ()>, wasmtime::Error> {
        let map_key_iter: &'_ mut libbpf_rs::MapKeyIter = self.table.get_mut(&self_)?;
        Ok(Ok(map_key_iter.next()))
    }

    fn drop(
        &mut self,
        rep: wasmtime::component::Resource<libbpf_rs::MapKeyIter>,
    ) -> wasmtime::Result<()> {
        self.table.delete(rep)?;
        Ok(())
    }
}

I got a compiler error of "borrowed data escapes outside of method
self_ escapes the method body here"

Thus I want to add a lifetime for MapKeyIter and modified the signature of next like

    fn next(
        &mut self,
        self_: wasmtime::component::Resource<libbpf_rs::MapKeyIter<'a>>,
    ) -> Result<Result<Option<Vec<u8>>, ()>, wasmtime::Error> {

It tells me lifetime mismatch and signature mismatch.

The solution for this we think is that wasmtime::component::bindgen!() generates Trait with explicitly lifetime annotation instead of elided anonymouse lifetime, for example,

            pub trait HostMapKeyIter<'a> {
                fn next(
                    &mut self,
                    self_: wasmtime::component::Resource<MapKeyIter<'a>>,
                ) -> wasmtime::Result<Result<Option<Value>, ()>>;
                fn drop(
                    &mut self,
                    rep: wasmtime::component::Resource<MapKeyIter<'a>>,
                ) -> wasmtime::Result<()>;
            }

then avoid lifetime mismatch and signature mismatch.

Could you share your insights with us? Please let us know if you have different solution for push a struct with reference filed into a ResourceTable.

Thanks,
Chengdong

view this post on Zulip Bryton (Jul 05 2024 at 07:34):

After we investigated wit bindgen marco, we realized that wit bindgen generates trait without lifetime for every resource type.

https://docs.rs/wasmtime-wit-bindgen/22.0.0/src/wasmtime_wit_bindgen/lib.rs.html#1307

            uwriteln!(self.src, "pub trait Host{camel} {{");

and

    fn generate_function_trait_sig(&mut self, func: &Function) {
        let wt = self.gen.wasmtime_path();
        self.rustdoc(&func.docs);

        if self.gen.opts.async_.is_import_async(&func.name) {
            self.push_str("async ");
        }
        self.push_str("fn ");
        self.push_str(&rust_function_name(func));
        self.push_str("(&mut self, ");
        for (name, param) in func.params.iter() {
            let name = to_rust_ident(name);
            self.push_str(&name);
            self.push_str(": ");
            self.print_ty(param, **TypeMode::Owned**);
            self.push_str(",");
        }

There is no option can control this.

view this post on Zulip Ramon Klass (Jul 05 2024 at 11:41):

I think that's what this with construct is meant for https://github.com/bytecodealliance/wasmtime/blob/main/crates/wasi-http/src/bindings.rs#L20-L37

A fast and secure runtime for WebAssembly. Contribute to bytecodealliance/wasmtime development by creating an account on GitHub.

view this post on Zulip Alex Crichton (Jul 08 2024 at 14:26):

At this time, no, you can't put anything with a lifetime into ResourceTable (unless it's 'static). That's required for a number of reasons related to memory safety at this time and would require some significant rearchitecting to enable that I think. I haven't tried too too hard though so it's mostly a gut feeling, if you'd like it might be reasonable to try to plumb a lifetime parameter around


Last updated: Dec 23 2024 at 13:07 UTC