bytecodealliance / wasmtime

A fast and secure runtime for WebAssembly
https://wasmtime.dev/
Apache License 2.0
15.48k stars 1.31k forks source link

WasiCtx and preopen #1772

Open donovano opened 4 years ago

donovano commented 4 years ago

Hi,

Wasi::new takes a WasiCtx parameter that can be created with environment args as shown in your examples on WASI and linking. With the wasmtime binary you can pass the --dir parameter to preopen a directory where the wasm module can read a file from. I did not so far get this to work when instantiating a WASI module using your API. It seems the args passed into the WasiCtx creation does not end up with directories being pre-opened. The end result is that file IO from a WASI module does not seem to work unless you are calling it from the wasmtime binary. Maybe I'm missing something? Thanks.

sunfishcode commented 4 years ago

Can you describe how you're setting up the WasiCtx? Are you calling preopened_dir to add the preopens?

donovano commented 4 years ago

Sure, the following is based on some code of wasmtime in run.rs. I suspect the File::open might be not correct but not sure. The wasm module tries to open a file in the current directory of the executable. Anyway...

   ...
   let mut linker = Linker::new(&store);
   let mut cx1 = wasi_common::WasiCtxBuilder::new();
   let mut path = Path::new(".");
   let mut file = match File::open(&path) {
      Err(why) => panic!("couldn't open file: {}",
            why.description()),
      Ok(file) => {println!("could open ."); file},
   };  
   cx1.preopened_dir(file.try_clone()?, ".");
   let cx1 = cx1.build()?;
   let wasi = Wasi::new(&store, cx1);
   //NOTE the following also did not work when passing the --dir=. parameter to the executable
   //let wasi = Wasi::new(&store, WasiCtx::new(std::env::args())?);
   wasi.add_to_linker(&mut linker)?;
   ...
sunfishcode commented 4 years ago

Offhand I don't see anything wrong there. Do you know what string the application code is attempting to open that isn't working?

donovano commented 4 years ago

Here is the simple code section from the wasm module. Note that this works when called from wasmtime (with --dir=.). The file is in the current directory:

...
let path = Path::new("somefile.txt");
let mut file = match File::open(path) {
...

I'll fish around for something else that might be causing this if you say that it all looks sound.

donovano commented 4 years ago

Solved the problem. start wasn't being called. Thanks for the help.

linouxis9 commented 4 years ago

I'm having a similar issue @donovano, may I ask which start was not being called?

Thank you!

alexandruradovici commented 7 months ago

Same problem here, any ideas?

alexandruradovici commented 7 months ago

It turns out that using

let (command, _instance) = wasmtime_wasi::bindings::sync::Command::instantiate(
        &mut store,
        &component,
        &mut linker,
    ).unwrap();

to instantiate the component make preopened_dir to work, but using

let example_res = Root::instantiate(&mut store, &component, &linker);
    match example_res {
        Ok((instance, _)) => {
            instance.interface0.call_funcall(&mut store).unwrap();
        }
        Err(e) => println!("Error at calling function {:?}", e),
    }

fails.

We use a reactor component, so I think we are missing some wasi initialization step, we just cannot figure out which one.