Skip to content

Cannot create, read and write using a wasm module #55

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jmcad opened this issue Feb 2, 2021 · 8 comments
Closed

Cannot create, read and write using a wasm module #55

jmcad opened this issue Feb 2, 2021 · 8 comments

Comments

@jmcad
Copy link

jmcad commented Feb 2, 2021

I've been trying to create a file and write data to it by using a WebAssembly module written in Rust:

#[no_mangle]
pub fn write() -> Result<(), io::Error> {
    println!("Trying to create a file");
    let mut file = File::create("./foo.txt")?;
    // let mut file = File::open("foo.txt")?;
    println!("I created a file");
    file.write_all(b"Hello, world!")?;
    Ok(())
}

#[no_mangle]
pub extern "C" fn waWrite() -> bool {
    let err = write();
    println!("I am in the waWrite function");
    match err {
        Ok(()) => {
            print!("GOOD");
            return true;
        }
        Err(_e) => {
            print!("GOOD");
            return false;
        }
    }
}

However this does not seem to work at all. Are there any solutions/workarounds for this problem or am I missing something obvious?

Here is my Go code:

func main() {
    // stdout to print WASI text
    dir, err := ioutil.TempDir("", "out")
    check(err)
    defer os.RemoveAll(dir)
    stdoutPath := filepath.Join(dir, "stdout")

    engine := wasmtime.NewEngine()
    store := wasmtime.NewStore(engine)
    linker := wasmtime.NewLinker(store)

    // configure WASI imports to write stdout into a file.
    wasiConfig := wasmtime.NewWasiConfig()
    wasiConfig.SetStdoutFile(stdoutPath)
    err = wasiConfig.PreopenDir(".", ".")
    check(err)

    args := []string{"foo.txt"} // file names
    wasiConfig.SetArgv(args)

    // set the version to the same as in the WAT.
    wasi, err := wasmtime.NewWasiInstance(store, wasiConfig, "wasi_snapshot_preview1")
    check(err)

    // link WASI
    err = linker.DefineWasi(wasi)
    check(err)

    // create the WebAssembly-module
    module, err := wasmtime.NewModuleFromFile(store.Engine, "rust_write.wasm")
    check(err)
    instance, err := linker.Instantiate(module)
    check(err)

    // export functions and memory from the WebAssembly module

    write := instance.GetExport("waWrite").Func()

    res, err := write.Call()
    check(err)
    if res == true {
        println("wrote to file")
    } else {
        println("didn't write to file")
    }

    out, err := ioutil.ReadFile(stdoutPath)
    check(err)
    fmt.Print(string(out))
}

func check(err error) {
    if err != nil {
        panic(err)
    }
}
@alexcrichton
Copy link
Member

I think that this is likely due to rust-lang/rust#79199, can you perhaps try recompiling with the latest Rust nightly and see if that fixes the issue for you?

@AndreaEsposit
Copy link

AndreaEsposit commented Feb 2, 2021

I get the same problem with the latest Rust nightly,
How do wasiConfig.PreopenDir(".", ".") and wasiConfig.SetArgv(args) work exactly?

@alexcrichton
Copy link
Member

SetArgv effectively configures the return value of env::args in Rust, and PreopenDir opens the first parameter as a host directory and the second parameter as the name of the guest directory.

@AndreaEsposit
Copy link

Oh, thank you for the explanation. Do you then have any idea why It doesn't work for me as well?
I tried using the same wasm module and wasmtime CLI like this wasmtime --dir=. --invoke waWrite rust_write.wasm
And get "failed to find a pre-opened file descriptor through which "foo.txt" could be opened"

@alexcrichton
Copy link
Member

Hm if it doesn't work with the wasmtime CLI then it may be that issue I linked? Are you sure you're using the latest nightly to compile the wasm?

@AndreaEsposit
Copy link

AndreaEsposit commented Feb 3, 2021

(I am using rustc 1.51.0-nightly) @alexcrichton
Alright, I implemented a very simple Wasm module that has just a main function that creates a file and writes "hello" to it. It works perfectly in wasmtime CLI just using the --mapdir flag, Unfortunately the code written in the "library" style (jmcad's crate compiled as cdylib) still doesn't work, is it a bug? Or is it just not meant to work with library-style binaries?

Could it be that the issue is that _start is not called when you directly --invoke the waWrite function?

@AndreaEsposit
Copy link

AndreaEsposit commented Feb 3, 2021

I found a solution here: rust-lang/rust#79997 (comment)

@alexcrichton
Copy link
Member

Ah oops sorry! I forgot that the new -Z flag was also needed. I'm glad it works for you though! I'm going to close this in that case then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants