简体   繁体   中英

How can I read an existing directory from WASM in Rust using wasmer-wasi?

I wrote a simple wasmer-wasi example that reads directory entries but it always fails.

wasi_fs_example/src/lib.rs :

#[no_mangle]
pub fn start() {
    std::fs::read_dir("/").unwrap();
}

runner/src/main.rs :

use wasmer::{Instance, Module, Store};
use wasmer_wasi::WasiState;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let wasm = std::fs::read("target/wasm32-wasi/debug/wasi_fs_example.wasm")?;

    let store = Store::default();
    let module = Module::new(&store, wasm)?;

    let mut wasi_env = WasiState::new("wasi_fs_example")
        .preopen_dir("target")?
        .finalize()?;

    let import_object = wasi_env.import_object(&module)?;
    let instance = Instance::new(&module, &import_object)?;

    let start = instance.exports.get_function("start")?;
    start.call(&[])?;

    Ok(())
}

This produce the error while running:

cargo build -p wasi_fs_example --target wasm32-wasi
cargo run -p runner
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: Custom { kind: Other, error: "failed to find a pre-opened file descriptor through which \"/\" could be opened" }', wasi_fs_example/src/lib.rs:6:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Full source code of the example is located here . Why doesn't it work?

Currently in Rust we can really only create WASI binaries, not libraries. WASI only works for the duration of a main function that needs to be there. Calling the wasi functions from anywhere else segfaults because libpreopen isn't initialized.

So to summarize, how to fix this currently:

  • Do not have lib.crate-type at all
  • Have the file be src/main.rs , not src/lib.rs
  • Have #![no_main] at the top of the src/main.rs
  • Use RUSTFLAGS="-Z wasi-exec-model=reactor" cargo +nightly build --target wasm32-wasi
  • Make sure that you call _initialize before anything else

https://github.com/WebAssembly/WASI/issues/24

https://github.com/rust-lang/rust/pull/79997

In my case:

wasi_fs_example/src/main.rs :

#![no_main]

#[no_mangle]
pub extern "C" fn start() {
    std::fs::read_dir("/").unwrap();
}

runner/src/main.rs :

...
let start = instance.exports.get_function("_initialize")?;
start.call(&[])?;

let start = instance.exports.get_function("start")?;
start.call(&[])?;
...
RUSTFLAGS="-Z wasi-exec-model=reactor" cargo +nightly build -p wasi_fs_example --target wasm32-wasi

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM