kawamuray / wasmtime-java

Java or JVM-language binding for Wasmtime
Apache License 2.0
127 stars 29 forks source link

Writing files from preopened directories with Reactors #22

Closed nicholasjackson closed 3 years ago

nicholasjackson commented 3 years ago

I have been trying to write to a pre-opened directory from a Wasm Reactor however I continually get the error.

Write fileopen /test.txt: errno 76

From looking into this I found this issue on wasmtime:

https://github.com/rust-lang/rust/pull/79997#issuecomment-759856446

It states that you must call _initialize in order to use pre-opened directories but I have tried this and failed to get it working.

I am initiating the runtime using the following code.

  public void init() {
    WasiCtx wasi = new WasiCtxBuilder().inheritStdout().inheritStderr().preopenedDir(Path.of("./"), "/").build();

    store = Store.withoutData(wasi);
    engine = store.engine();
  }

Then from Go I have a simple function, the complete wat can be found below.

//go:export write_file
func write_file() int {
    fmt.Printf("Write file")

    err := ioutil.WriteFile("/test.txt", []byte("Hello"), 0644)
    if err != nil {
        fmt.Println(err)
        return 1
    }

    return 0
}

Before callingfile_write I call _initialize like so.

    Func f = linker.get(store, "", "_initialize").get().func();
    WasmFunctions.Consumer0 fn = WasmFunctions.consumer(store, f);
    fn.accept();

I did get this working with a Command and adding the file write code into main with the wasmtime cli but not successfully from a reactor.

Kind regards,

Nic

nicholasjackson commented 3 years ago

I am just looking at another issue where this was raised, I am actually using windows at the moment, will try on my mac to see if I get the same issues.

nicholasjackson commented 3 years ago

I have tested this on both windows and on my mac (both with absolute and relative paths) and in both instances I get an error 76 and the report that the file is not accessible.

Go wat: go.zip

kawamuray commented 3 years ago

The _initialize function in your wasm module has empty body so it's no-op.

$ grep -A 3 '^ *(func $_initialize' go.wat
  (func $_initialize (type 6))
  (func $hello (type 2) (param i32) (result i32)
    (local i32 i32 i32 i64 i32)
    global.get 0

Actually I've had the same experience before and it turns out that I have to implement my own _initialize function when I build a wasm module as a reactor. This insight is specific to the Rust compiler of the year older version than the current latest so I'm not sure if that's still a case, but at least your tinygo compiler doesn't seem to support generating appropriate _initialize function from the generated wasm.

Please refer my blog post for the detail: https://engineering.linecorp.com/en/blog/adding-experimental-webassembly-support-to-decaton-part-1/#AddingexperimentalWebAssemblysupporttoDecatonPart1-ImplementaDecatonprocessorwithWasm/WASI

nicholasjackson commented 3 years ago

So I did some digging and it actually seems that TinyGo correctly pre-opening the files however it only does this in the command _start method.

However, as a workaround, if I rename the export _intialize then wasmtime correctly calls this method before running my module functions and this sets up all the directories.

sed -i 's/(export "_start" (func \$$_start/(export "_initialize" (func \$$_start/g' ../go.wat

I will report these things back to the TinyGo team. Next up are memory issues.