Open dkegel-fastly opened 3 years ago
Here's main.wasm zipped: main.wasm.zip
I'm not seeing anything particularly enlightening under strace
. Because of that, my current hypothesis is that something is happening in user space that doesn't involve syscalls, and that the tinygo
wasi implementation (correctly? incorrectly? not sure) doesn't recognize "test.txt"
as being within the preopened directory ".", so it fails because it doesn't know how to find that file.
Can you try modifying the program to read `"./test.txt" and see whether that works or not?
already tried that, no joy.
Note that tinygo wasi does recognize test.txt when run without wizer (as demonstrated).
Updating wasmtime from 0.27 to 0.28 did not fix this issue, fwiw.
If I tell Wizer that the initialization function is the _start
function via --init-func _start
, then the wasm module runs just fine (and then Wizer snapshots the state after its execution finishes). Of course, we don't want to run the whole program during wizening, but this suggests that the issue is not the WASI context, as I originally suspected, and is instead something to do with the wasm itself.
I suspect that tinygo is producing wasm modules whose exported functions assume that global constructors have run and that the tinygo runtime is already initialized. We hit this with C++, where we have to make sure that we call global constructors before continuing with application-level initialization (Rust does not have global constructors, and therefore avoids this issue). Instead, I think tinygo is assuming that _start
is the very first thing that is ever called, and does its runtime/global ctor initialization there. That assumption is violated by Wizer's execution model.
I wonder if this program (modulo any simple errors I may have written, as a non-gopher) works with Wizer?
package main
var theText string
//go:export wizer.initialize
func WizerInitialize() {
theText = "initialized!"
}
func main() {
println("theText: ", theText)
}
Even better would be a wizer.init
that initializes a global using something that definitely relies on the runtime/global ctors having already been initialized, but I'm not familiar enough with go/tinygo to know what that something might be.
So if my new hypothesis is correct there are two ways to fix this:
__wasm_call_ctors
is and call that is the very first thing you do in the initialization function, and somehow make it so that that doesn't get called again when _start
is calledBoth of these are tinygo toolchain issues, but once we figure it out, we should document it and have examples in here.
That little test program does print out theText: initialized!
FWIW reading from stdin is working out as a workaround.
Given the program
This succeeds, and outputs foobar as expected:
but this
fails with
Setting RUST_LOG=debug shows that it is at least preopening the directory:
Passing a bad directory to --dir does abort, so it is at least opening the directory.
This is on mac, so I have not gone through the agony of using dtruss to see if it is actually trying to open a file.