Code Monkey home page Code Monkey logo

wasmtime-go's Introduction

wasmtime-go

Go embedding of Wasmtime

A Bytecode Alliance project

CI status Documentation Code Coverage

Installation

go get -u github.com/bytecodealliance/wasmtime-go/[email protected]

Be sure to check out the API documentation!

This Go library uses CGO to consume the C API of the Wasmtime project which is written in Rust. Precompiled binaries of Wasmtime are checked into this repository on tagged releases so you won't have to install Wasmtime locally, but it means that this project only works on Linux x86_64, macOS x86_64 , and Windows x86_64 currently. Building on other platforms will need to arrange to build Wasmtime and use CGO_* env vars to compile correctly.

This project has been tested with Go 1.13 or later.

If you are a bazel user, add following to your WORKSPACE file:

go_repository(
    name = "com_github_bytecodealliance_wasmtime_go",
    importpath = "github.com/bytecodealliance/wasmtime-go/v21",
    version = "v21.0.0",
)

Usage

A "Hello, world!" example of using this package looks like:

package main

import (
    "fmt"
    "github.com/bytecodealliance/wasmtime-go/v21"
)

func main() {
    // Almost all operations in wasmtime require a contextual `store`
    // argument to share, so create that first
    store := wasmtime.NewStore(wasmtime.NewEngine())

    // Compiling modules requires WebAssembly binary input, but the wasmtime
    // package also supports converting the WebAssembly text format to the
    // binary format.
    wasm, err := wasmtime.Wat2Wasm(`
      (module
        (import "" "hello" (func $hello))
        (func (export "run")
          (call $hello))
      )
    `)
    check(err)

    // Once we have our binary `wasm` we can compile that into a `*Module`
    // which represents compiled JIT code.
    module, err := wasmtime.NewModule(store.Engine, wasm)
    check(err)

    // Our `hello.wat` file imports one item, so we create that function
    // here.
    item := wasmtime.WrapFunc(store, func() {
        fmt.Println("Hello from Go!")
    })

    // Next up we instantiate a module which is where we link in all our
    // imports. We've got one import so we pass that in here.
    instance, err := wasmtime.NewInstance(store, module, []wasmtime.AsExtern{item})
    check(err)

    // After we've instantiated we can lookup our `run` function and call
    // it.
    run := instance.GetFunc(store, "run")
    if run == nil {
        panic("not a function")
    }
    _, err = run.Call(store)
    check(err)
}

func check(e error) {
    if e != nil {
        panic(e)
    }
}

Contributing

So far this extension has been written by folks who are primarily Rust programmers, so it's highly likely that there's some faux pas in terms of Go idioms. Feel free to send a PR to help make things more idiomatic if you see something!

To work on this extension locally you'll first want to clone the project:

$ git clone https://github.com/bytecodealliance/wasmtime-go

Next up you'll want to have a local Wasmtime build available.

You'll need to build at least the wasmtime-c-api crate, which, at the time of this writing, would be:

$ cargo build -p wasmtime-c-api

Once you've got that you can set up the environment of this library with:

$ ./ci/local.sh /path/to/wasmtime

This will create a build directory which has the compiled libraries and header files. Next up you can run normal commands such as:

$ go test

And after that you should be good to go!

Release Checklist

First run:

$ python3 ci/download-wasmtime.py
$ go test

Make sure everything passes at the current version.

Next run:

$ git ls-files | xargs sed -i 's/v16/v17/g'
$ python3 ci/download-wasmtime.py
$ go test

Fix all errors and such and then commit and make a PR.

Once merged checkout main and do:

$ rm .gitignore
$ python3 ci/download-wasmtime.py
$ git add .
$ git commit -m 'v21.0.0 release artifacts'
$ git tag v21.0.0

and push up the tag

wasmtime-go's People

Contributors

alexcrichton avatar arl avatar avidal avatar c0mm4nd avatar cclauss avatar danielledeleo avatar devanshu24 avatar fgsch avatar gggrafff avatar guregu avatar howjmay avatar hywan avatar jeschkies avatar koponen-styra avatar kyleconroy avatar liangyuanpeng avatar mrsharff avatar olivierlemasle avatar samscott89 avatar srenatus avatar turbolent avatar vlkv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wasmtime-go's Issues

Memory operation is inconvenient

I found it's hard to operate the memory, and I'm confused on the Extern.Memory() method. Are there any difference between wasmer's and wasmtime's memory?

In wasmer, memory can be directly gotten from the instance, and the []byte style memory data is quite easy to write and input. Like this example

memory := instance.Memory.Data()[inputPointer:]

but I have to export one from the instance first in wasmtime, which is confusing. And I have to *(*[]byte) every time.

memory := instance.GetExport("memory").Memory()

Memory leak in instance creation

Running the following to see the memory leak in action:


import (
        "github.com/bytecodealliance/wasmtime-go"
        "runtime"
)

func main() {
        wasm, err := wasmtime.Wat2Wasm(`
      (module
        (import "" "hello" (func $hello))
        (func (export "run")
          (call $hello))
      )
    `)
        check(err)

        for {
                store := wasmtime.NewStore(wasmtime.NewEngine())
                module, err := wasmtime.NewModule(store.Engine, wasm)
                check(err)

                item := wasmtime.WrapFunc(store, func() {})
                instance, err := wasmtime.NewInstance(store, module, []*wasmtime.Extern{item.AsExtern()})
                check(err)

                // The rest is not required for the leak.

                run := instance.GetExport("run").Func()
                _, err = run.Call()
                check(err)

                runtime.GC()
        }
}

func check(e error) {
        if e != nil {
                panic(e)
        }
}

Go link failure on Ubuntu 18.04

After updating to v0.26.1 of wasmtime-go, a project I work on started failing when running Go tests on Linux (Ubuntu 18.04).

/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/root/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/linux-x86_64/libwasmtime.a(rand-c9e73dea03c33dfe.rand.7g47d74v-cgu.8.rcgu.o): In function `_ZN3std4sync4once4Once9call_once28_$u7b$$u7b$closure$u7d$$u7d$17hd38fe0856a08c7c8E.llvm.16281869784479911949':
rand.7g47d74v-cgu.8:(.text._ZN3std4sync4once4Once9call_once28_$u7b$$u7b$closure$u7d$$u7d$17hd38fe0856a08c7c8E.llvm.16281869784479911949+0x1a): undefined reference to `pthread_atfork'
/root/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/linux-x86_64/libwasmtime.a(rand-c9e73dea03c33dfe.rand.7g47d74v-cgu.8.rcgu.o): In function `_ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h5210ace1770a56e9E.llvm.16281869784479911949':
rand.7g47d74v-cgu.8:(.text._ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h5210ace1770a56e9E.llvm.16281869784479911949+0x1a): undefined reference to `pthread_atfork'
collect2: error: ld returned 1 exit status

Based on some research (here, here, and here), it looks like it might be fixed simply by adding -pthread to the LDFLAGS line in ffi.go (that solves the issue for me, but I'm unsure if it's 100% correct).

feedback regarding return of nil values

func (c *Caller) GetExport(name string) *Extern {

From the README:

run := instance.GetExport("run").Func()
 _, err = run.Call()

The call to both GetExport and Func both can return a nil value, and in the example above, could panic when .Func is invoked. Ideally the export is caught as non-existent through an error returned from GetExport prior. It's not as nice of an API from an ergonomic perspective, and I see the convenience in the current pattern.

Would you be open to a PR that attempts a safer API here? I use the Rust wasmtime crate, and though it is more verbose, I prefer the error handling imposed upon us. Also, I think its important for wasm ecosystem as a whole to present a safe & resilient toolset (not saying this Go module isn't!, but I would like to see if I can help improve it).

leak of virtual memory

When I run the below program

func getWasm() []byte {
	wasm, _ := wasmtime.Wat2Wasm(`(module
    (func (export "foo")
    )
)`)
	if len(os.Args) == 1 {
		return wasm
	}
	f, e := os.Open("foo.wasm")
	defer f.Close()
	s, e := io.ReadAll(f)
	return s
}

func test(wasm []byte) {
	eng := wasmtime.NewEngine()
	store := wasmtime.NewStore(eng)
	module, _ := wasmtime.NewModule(store.Engine, wasm)
	inst, _ := wasmtime.NewInstance(store, module, []*wasmtime.Extern{})
	inst.GetFunc("foo").Call()
}

func main() {
	wasm := getWasm()
	for i := 0; i < 10; i++ {
		fmt.Println(i)
		test(wasm)
		time.Sleep(3 * time.Second)
		runtime.GC()
	}
}

If I don't provide any argument in the command line to let it run wasm code compiled from wat as below

(module
    (func (export "foo")
    )
)

everything is fine.

But if I provide one argument to let it run wasm code compile from c code as below

void foo() {
}

virtual memory usage increase 6G in every iteration in the main function.

the c code is compiled by emcc and the command line is

emcc foo.c -o foo.wasm -s EXPORTED_FUNCTIONS=_foo --no-entry

go get fails with "fatal error: 'wasm.h' file not found"

I've been following the instructions to install wasmtime-go with go get -u and it fails with this error message:

$ go get -u github.com/bytecodealliance/wasmtime-go                                                                                      
# github.com/bytecodealliance/wasmtime-go
../../bytecodealliance/wasmtime-go/config.go:3:11: fatal error: 'wasm.h' file not found
 #include <wasm.h>
          ^~~~~~~~
1 error generated.

My bet is that I need to setup the local build for development and that cargo build -p wasmtime-c-api will fix it, but I wanted to report this issue first.

More information:

$ wasmtime --version
wasmtime 0.16.0
$ go version
go version go1.14 darwin/amd64

Cannot create, read and write using a wasm module

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)
    }
}

Cache options don't do anything?

The package exposes wasm config methods for configuring the compiler cache, but I've never seen anything show up in the cache directory. I've tried with the default ($XDG_CACHE_HOME / $XDG_CACHE_DIRS) as well as explicitly setting the path and have never seen anything in it.

wasmtime.Trap is difficult to inspect

Currently, unless I'm mistaken, we'll have to check the wasmtime.Trap's Message() to figure out what happened.

While there could be user-defined traps, there seem to be a bunch of pre-defined ones in wasmtime:
https://github.com/bytecodealliance/wasmtime/blob/bde955579336e124b2c01b3164314bf2d6eec378/cranelift/codegen/src/ir/trapcode.rs#L8-L54

It would be nice if these were exposed to Go, allowing for use with errors.Is() or errors.As(), instead of inspecting the message string.

WASI error

My try on WASI

	var engine = wasmtime.NewEngine()

	cfg := wasmtime.NewWasiConfig()
	err := cfg.PreopenDir(".", ".") // what's the different between path and guest path? RW & ReadOnly?
	if err != nil {
		panic(err)
	}

	args := []string{"1", "2"} // file names
	cfg.SetArgv(args)

	store := wasmtime.NewStore(engine)
	wasi, err := wasmtime.NewWasiInstance(store, cfg, "wasi_unstable")
	if err != nil {
		panic(err)
	}

	raw := RawWASM // WASM binary from https://github.com/bytecodealliance/wasmtime/blob/master/docs/WASI-tutorial.md#from-rust
	module, err := wasmtime.NewModule(store, raw)
	if err != nil {
		panic(err)
	}

	linker := wasmtime.NewLinker(store)
	err = linker.DefineWasi(wasi)
	if err != nil {
		panic(err)
	}

	_, err = linker.Instantiate(module)
	if err != nil {
		panic(err) // <- panic here
	}

Panic Message

FAIL: TestWASM (0.06s)
panic: unknown import: `wasi_snapshot_preview1::proc_exit` has not been defined [recovered]
        panic: unknown import: `wasi_snapshot_preview1::proc_exit` has not been defined

goroutine 6 [running]:
testing.tRunner.func1.1(0xe51ee0, 0xc000006070)
        c:/go/src/testing/testing.go:940 +0x2fc
testing.tRunner.func1(0xc000128120)
        c:/go/src/testing/testing.go:943 +0x400
panic(0xe51ee0, 0xc000006070)
        c:/go/src/runtime/panic.go:969 +0x174
github.com/maoxs2/wasm-example.Exec(0x1)
        C:/Users/c/wasm-example/wasm.go:57 +0x51d
github.com/maoxs2/wasm-example_test.TestWASM(0xc000128120)
        C:/Users/c/wasm-example/wasm_test.go:11 +0x53
testing.tRunner(0xc000128120, 0xe89ae0)
        c:/go/src/testing/testing.go:991 +0xe3
created by testing.(*T).Run
        c:/go/src/testing/testing.go:1042 +0x35e
FAIL    github.com/maoxs2/wasm-example  0.421s
FAIL

Do I miss any other step? By the way, I think some more go-style docstrings and examples are necessary.

And let me ask another off-topic question. My need is to create a sandbox runtime like ethereum's EVM, so do I need to use WASI, or just use WASM? Personally, I think using WASI's file io and argv is apparently easier than operating WASM's memory. Could you give me some suggestions as guru?

panic when calling the same function from different instances

In the example below, I create a module and then spin up multiple instances off of that module in their own goroutine. Then I have each instance call add_one() at the same time. This results in the following error:

thread '<unnamed>' panicked at 'already borrowed: BorrowMutError', crates/wasmtime/src/instance.rs:511:30

This is on macOS 10.15.7 with Go 1.16.4. Am I missing something obvious like a limit of 1 instance per module at a time, or did I hit a bug?

package main

import (
	"log"
	"time"

	"github.com/bytecodealliance/wasmtime-go"
)

var example = []byte(`
(module
  (type $add_one_t (func (param i32) (result i32)))
  (func $add_one_f (type $add_one_t) (param $value i32) (result i32)
	local.get $value
	i32.const 1
	i32.add)
  (export "add_one" (func $add_one_f)))
`)

var startC = make(chan struct{})

func runInstance(store *wasmtime.Store, module *wasmtime.Module) {
	instance, err := wasmtime.NewInstance(store, module, nil)
	if err != nil {
		log.Print(err.Error())
		return
	}

	// Wait until all goroutines are spun up.
	<-startC

	if _, err = instance.GetFunc("add_one").Call(1); err != nil {
		log.Print(err.Error())
	}
}

func main() {
	// Compile the example to wasm.
	data, err := wasmtime.Wat2Wasm(string(example))
	if err != nil {
		log.Fatal(err.Error())
	}

	// Create a new module for the example.
	store := wasmtime.NewStore(wasmtime.NewEngine())
	module, err := wasmtime.NewModule(store.Engine, data)
	if err != nil {
		log.Fatal(err.Error())
	}

	// Spin up 10 goroutines, each with its own instance derived from the
	// same module.
	for i := 0; i < 10; i++ {
		go runInstance(store, module)
	}

	// Sleep for a bit to allow the goroutines to set their instances up. Then
	// signal all instances to call the add_one() function.
	time.Sleep(20 * time.Millisecond)
	close(startC)

	select {}
}

Apple M1 Support

Is this planned? Is this something that would be helpful for me to add and PR?

how to implement high-level interactions?

I'm trying to operate string with wastime-go.

As a newbie of rust, I found it's impossible to extern "C" a function with &str and it seems that I have to use ptr: *const u8, len: usize.

It's OK to use these two args in func to export a string. But when I wanna import the new string into WASM, I failed to use fn get_ptr() -> (*const u8, usize); to load the new string.

Then I found wasm-bindgen, which is a pretty good lib enabling using &str in extern "C". However when I try the new WASM file compiled with wasm-bindgen, the go panic with error panic: wrong number of imports provided, 1 != 5 though I just write one extern "C" in rust extern "C" { fn print_str(s: &str); }.

So how should I correctly operate the string/bytes with the WASM's toolchain and wasmtime-go? Or am I have to implement a plugin like npm's @wasm-tool/wasm-pack-plugin for bindgen?

Installation package fail

lanrendeMacBook-Pro:go-control-plane lanren$ go get -u github.com/bytecodealliance/[email protected]
go: finding github.com/bytecodealliance v0.16.1
go: finding github.com/bytecodealliance/wasmtime-go v0.16.1
go: finding github.com v0.16.1
go: downloading github.com/bytecodealliance/wasmtime-go v0.16.1
go: extracting github.com/bytecodealliance/wasmtime-go v0.16.1
# github.com/bytecodealliance/wasmtime-go
../../../gopath/pkg/mod/github.com/bytecodealliance/[email protected]/module.go:7:14: warning: assigning to 'wasm_byte_t *' (aka 'char *') from 'uint8_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
../../../gopath/pkg/mod/github.com/bytecodealliance/[email protected]/module.go:14:14: warning: assigning to 'wasm_byte_t *' (aka 'char *') from 'uint8_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]

.gitignore causes trouble with vendoring

We're using wasmtime-go in OPA.

When users that use the opa golang package

  • vendor their dependencies, and
  • update their opa package (go get -u github.com/open-policy-agent/opa), and
  • git add go.mod go.sum vendor/
    ...then they'll end up with too little of the wasmtime-go package in their git repo. The build will then fail with something like
build github.com/bytecodealliance/wasmtime-go/build/include: cannot load github.com/bytecodealliance/wasmtime-go/build/include: open /home/runner/work/rego-playground/rego-playground/vendor/github.com/bytecodealliance/wasmtime-go/build/include: no such file or directory

This is because the build/ entry in .gitignore hinders necessary files from being picked up by git. using git add -f vendor/ will resolve this, but it's a stumbling block we should remove.

What do you think? I'd be happy to create a PR with some exceptions (as soon as I'm sure what they'll be ๐Ÿ˜„).

Panic while using Memory.Data() or .UnsafeData()

WASM

lib.rs

#[no_mangle]
pub extern fn string() ->  *const u8 {
    b"Hello, World!\0".as_ptr()
}

cargo build --target wasm32-unknown-unknown

GO

	f, _ := os.Open(wasmFile)
	wasm, _ := ioutil.ReadAll(f)

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

	module, err := wasmtime.NewModule(store, wasm)
	if err != nil {
		panic(err)
	}

	instance, err := wasmtime.NewInstance(store, module, []*wasmtime.Extern{})
	if err != nil {
		panic(err)
	}

	mem := instance.GetExport("string").Memory()
	run := instance.GetExport("string").Func()
	ptr, err := run.Call()
	if err != nil {
		panic(err)
	}

	log.Println(mem.Data(), mem.DataSize()) // Panic here
	log.Print(mem.UnsafeData())

Trace

PS C:\Users\c\Desktop\wasm-example> go run .
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x0 pc=0x4e1149]

goroutine 1 [running]:
github.com/bytecodealliance/wasmtime-go.(*Memory).ptr(...)
        C:/Users/c/go/pkg/mod/github.com/bytecodealliance/[email protected]/memory.go:35
github.com/bytecodealliance/wasmtime-go.(*Memory).Data.func1(0x0, 0x0)
        C:/Users/c/go/pkg/mod/github.com/bytecodealliance/[email protected]/memory.go:56 +0x29
github.com/bytecodealliance/wasmtime-go.(*Memory).Data(0x0, 0x0)
        C:/Users/c/go/pkg/mod/github.com/bytecodealliance/[email protected]/memory.go:56 +0x32
main.Run(0xe110c0, 0x38)
        C:/Users/c/Desktop/wasm-example/func.go:52 +0x239
main.main()
        C:/Users/c/Desktop/wasm-example/main.go:6 +0x3d
exit status 2

same error on WSL(kali) // codes are pruned so line from main func is different

kali@DESKTOP-E6K5FGU:/mnt/c/Users/c/Desktop/wasm-example$ go run .
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x63bed2]

goroutine 1 [running]:
github.com/bytecodealliance/wasmtime-go.(*Memory).ptr(...)
        /home/kali/go/pkg/mod/github.com/bytecodealliance/[email protected]/memory.go:35
github.com/bytecodealliance/wasmtime-go.(*Memory).Data.func1(0x0, 0x0)
        /home/kali/go/pkg/mod/github.com/bytecodealliance/[email protected]/memory.go:56 +0x22
github.com/bytecodealliance/wasmtime-go.(*Memory).Data(0x0, 0x0)
        /home/kali/go/pkg/mod/github.com/bytecodealliance/[email protected]/memory.go:56 +0x2b
main.Run(0xf8bc8d, 0x38)
        /mnt/c/Users/c/Desktop/wasm-example/func.go:50 +0x232
main.main()
        /mnt/c/Users/c/Desktop/wasm-example/main.go:6 +0x36
exit status 2

Expect to see

The whole mem data and being able to fetch string "Hello, World" from it

Just like this wasmer's example: https://github.com/wasmerio/go-ext-wasm#read-the-memory

By the way, we need more production examples based on C/Rust codes rather than WAT.

Is it safe to re-enter an instance?

Here re-enter means Go host functions call Wasm code again, and form a call chain like below:

Go -> Wasm -> Go -> Wasm

I know it is safe to use:

Go -> Wasm -> Go

However, if Go calls Wasm again, then there is a re-enter of the Wasm instance, is it still safe?

Change default branch name

As a policy, the Bytecode Alliance is changing the default branch names in all repositories. We would like for all projects to change the default to main by June 26. (We mention June 26th because there is some suggestion that GitHub may be adding the ability to make this process more seamless. Feel free to wait for that, but only up to June 26. We'll provide further support and documentation before that date.)

Please consider this a tracking issue. It is not intended for public debate.

  • Change branch name
  • Update CI
  • Update build scripts
  • Update documentation

Panic caused by invoking exported function returned from Caller

EDIT: sorry, this isn't a great bug title.

While making changes to address the memory leak in #57, I've run into a panic inside wasmtime-go. It seems that invoking exported functions returned from the Caller invalidates the global freelist.

Here's a minimal example:

package main

import (
	"fmt"
	"runtime/debug"

	"github.com/bytecodealliance/wasmtime-go"
)

func main() {

	bs, err := wasmtime.Wat2Wasm(`
	(module
		(import "" "f2" (func $f2))
		(func (export "f1")
			(call $f2)
			(call $f2))
		(func (export "f3")
			(nop)))
	`)
	check(err)

	store := wasmtime.NewStore(wasmtime.NewEngine())

	imports := []*wasmtime.Extern{
		wasmtime.NewFunc(store, wasmtime.NewFuncType(nil, nil), func(c *wasmtime.Caller, args []wasmtime.Val) ([]wasmtime.Val, *wasmtime.Trap) {
			fmt.Printf("f2(): caller:%+v\n", c)
			fn := c.GetExport("f3").Func()
			fmt.Printf("  --> fn=%+v\n", fn)
			defer func() {
				if e := recover(); e != nil {
					fmt.Println(string(debug.Stack()))
				}
			}()
			_, err := fn.Call()
			check(err)
			fmt.Printf("  --> returning\n")
			return nil, nil
		}).AsExtern(),
	}

	module, err := wasmtime.NewModule(store.Engine, bs)
	check(err)

	instance, err := wasmtime.NewInstance(store, module, imports)
	check(err)

	_, err = instance.GetExport("f1").Func().Call()
	check(err)
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}

Running this produces the following panic:

$ go run main.go
f2(): caller:&{ptr:0x7ffdfee72a50 freelist:0xc000134000}
  --> fn=&{_ptr:0x3184720 _owner:0xc0001221a0 freelist:0xc000134000}
  --> returning
f2(): caller:&{ptr:0x7ffdfee72a50 freelist:<nil>}
  --> fn=&{_ptr:0x317b880 _owner:0xc000122220 freelist:<nil>}
goroutine 1 [running, locked to thread]:
runtime/debug.Stack(0xc00013f440, 0x112dde0, 0x15aab00)
        /usr/local/go/src/runtime/debug/stack.go:24 +0x9f
main.main.func1.1()
        /home/torin/scratch/wasmtime-use-caller/main.go:32 +0x46
panic(0x112dde0, 0x15aab00)
        /usr/local/go/src/runtime/panic.go:969 +0x175
github.com/bytecodealliance/wasmtime-go.(*freeList).clear(0x0)
        /home/torin/go/pkg/mod/github.com/bytecodealliance/[email protected]/freelist.go:66 +0x4e
github.com/bytecodealliance/wasmtime-go.(*Func).ptr(...)
        /home/torin/go/pkg/mod/github.com/bytecodealliance/[email protected]/func.go:377
github.com/bytecodealliance/wasmtime-go.(*Func).Type.func1(0xc000122240, 0x0)
        /home/torin/go/pkg/mod/github.com/bytecodealliance/[email protected]/func.go:392 +0x2f
github.com/bytecodealliance/wasmtime-go.(*Func).Type(0xc000122240, 0xc00012a080)
        /home/torin/go/pkg/mod/github.com/bytecodealliance/[email protected]/func.go:392 +0x2b
github.com/bytecodealliance/wasmtime-go.(*Func).Call(0xc000122240, 0x0, 0x0, 0x0, 0xc00013f930, 0x1, 0x1, 0x3e)
        /home/torin/go/pkg/mod/github.com/bytecodealliance/[email protected]/func.go:445 +0x45
main.main.func1(0xc000112300, 0x15f30b8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
        /home/torin/scratch/wasmtime-use-caller/main.go:35 +0x1a8
github.com/bytecodealliance/wasmtime-go.goTrampolineNew.func2(0xc00013fa88, 0x114c708, 0x0, 0x15f30b8, 0x0, 0x0, 0xc000112300, 0x15f30b8, 0x0, 0x0, ...)
        /home/torin/go/pkg/mod/github.com/bytecodealliance/[email protected]/func.go:123 +0x8c
github.com/bytecodealliance/wasmtime-go.goTrampolineNew(0xc000134000, 0x7ffdfee72a50, 0x0, 0x8, 0x8, 0x0)
        /home/torin/go/pkg/mod/github.com/bytecodealliance/[email protected]/func.go:135 +0x2e5
github.com/bytecodealliance/wasmtime-go._cgoexpwrap_fa971eff394f_goTrampolineNew(0xc000134000, 0x7ffdfee72a50, 0x0, 0x8, 0x8, 0x0)
        _cgo_gotypes.go:2818 +0x8e
github.com/bytecodealliance/wasmtime-go._Cfunc_go_wasmtime_func_call(0x317a7d0, 0x0, 0x0, 0x0, 0x0, 0xc00012e040, 0xc000134000, 0x0)
        _cgo_gotypes.go:638 +0x4e
github.com/bytecodealliance/wasmtime-go.(*Func).Call.func1(0xc000122160, 0x0, 0x15f30b8, 0x0, 0x0, 0x0, 0x15f30b8, 0x0, 0x0, 0xc00012e040, ...)
        /home/torin/go/pkg/mod/github.com/bytecodealliance/[email protected]/func.go:510 +0xe8
github.com/bytecodealliance/wasmtime-go.(*Func).Call(0xc000122160, 0x0, 0x0, 0x0, 0xc000116638, 0xc000114270, 0x0, 0x0)
        /home/torin/go/pkg/mod/github.com/bytecodealliance/[email protected]/func.go:510 +0x34d
main.main()
        /home/torin/scratch/wasmtime-use-caller/main.go:48 +0x209

The problem seems to be due to how the global freelist is managed: https://github.com/bytecodealliance/wasmtime-go/blob/main/func.go#L515

When the Go-defined function is called for the first time, it invokes the exported function "f3". Before returning, the Func.Call() implementation deletes the caller_id from the global freelist. The second time the Go-defined function is invoked via the trampoline, the global freelist doesn't contain the caller_id key and so the supplied Caller has a null freelist.

Perhaps the global freelist structure should maintain a stack of freelists for each caller so that they can be pushed and popped (e.g., map[C.size_t][]*freeList)? Also, I suppose the same issue could apply to the global caller panics structure. Not sure.

Thanks for all your hard work on this package!

Non-deterministic fatal go runtime crashes on macOS

Hi there!

I'm running into some non-deterministic go runtime crashes on macOS w/ v0.23.0. Here's an example:

package main

import (
	"fmt"

	"github.com/bytecodealliance/wasmtime-go"

	_ "github.com/bytecodealliance/wasmtime-go/build/include"        // to include the C headers.
	_ "github.com/bytecodealliance/wasmtime-go/build/linux-x86_64"   // to include the static lib for linking.
	_ "github.com/bytecodealliance/wasmtime-go/build/macos-x86_64"   // to include the static lib for linking.
	_ "github.com/bytecodealliance/wasmtime-go/build/windows-x86_64" // to include the static lib for linking.
)

func main() {

	bs, err := wasmtime.Wat2Wasm(`
	(module
		(func (export "f1")
			(unreachable)))
	`)
	check(err)

	for i := 0; ; i++ {
		fmt.Println("i:", i)
		store := wasmtime.NewStore(wasmtime.NewEngine())

		module, err := wasmtime.NewModule(store.Engine, bs)
		check(err)

		instance, err := wasmtime.NewInstance(store, module, nil)
		check(err)

		_, err = instance.GetExport("f1").Func().Call()
		if err == nil {
			panic("expected error")
		}
	}

}

func check(e error) {
	if e != nil {
		panic(e)
	}
}

If you run this program on macOS, it should crash eventually (the last couple runs on my laptop took about 150 iterations, but it's not consistent).

It seems like something nasty is happening in the runtime when the unreachable instruction is executed.

Here's the output from the last run:

$ go run -mod=vendor main.go
i: 0
i: 1
<--------------8< snip snip 8<----------------->
i: 296
signal 16 received but handler not on signal stack
fatal error: non-Go code set up signal handler without SA_ONSTACK flag

runtime stack:
runtime: unexpected return pc for runtime.sigtramp called from 0xc000127c28
stack: frame={sp:0xc0001277b0, fp:0xc0001277c0} stack=[0xc00011f6e0,0xc000127ae0)
000000c0001276b0:  000000c0001276d0  0000000004049665 <runtime.sigNotOnStack+133>
000000c0001276c0:  0000000004c15568  0000000000000039
000000c0001276d0:  000000c000127728  00000000040483db <runtime.adjustSignalStack+411>
000000c0001276e0:  0000000000000010  000000c0001276f8
000000c0001276f0:  000000c000127738  0000000008c22000
000000c000127700:  0000000000010000  0000000000000001
000000c000127710:  000000c00010a330  0000000004c15c30
000000c000127720:  0000000000000000  000000c0001277a0
000000c000127730:  0000000004048131 <runtime.sigtrampgo+369>  000000c000000010
000000c000127740:  0000000004e8aea0  000000c000127760
000000c000127750:  0000000000000000  0000000000000000
000000c000127760:  0000000000000000  0000000000000000
000000c000127770:  0000000000000000  0000000000000000
000000c000127780:  0000000000000000  000000c000000180
000000c000127790:  000000c000127c28  000000c000127c90
000000c0001277a0:  000000c0001277f0  0000000004067db3 <runtime.sigtramp+51>
000000c0001277b0: <0000000000000010 !000000c000127c28
000000c0001277c0: >000000c000127c90  000000c000127c90
000000c0001277d0:  d1560bb8e9a711de  000000000000013e
000000c0001277e0:  000000000000013d  0000000000000200
000000c0001277f0:  000000c000127800  00007fff6c4b05fd
000000c000127800:  000000c000127dd8  0000000000000000
000000c000127810:  0000000000000000  0000000000000000
000000c000127820:  00000000000000de  0000000037140000
000000c000127830:  000000000600a318  0000000004e8aea0
000000c000127840:  000000c000000180  0000000000000008
000000c000127850:  0000000006000108  0000000000000000
000000c000127860:  000000c000127dd8  000000c000127d48
000000c000127870:  0000000004beb8e0  0000000000003001
000000c000127880:  0000000000000018  0000000000000000
000000c000127890:  ffffffffffffffff  000000000000013e
000000c0001278a0:  000000000000013d  0000000000000200
000000c0001278b0:  000000000400ea3b <runtime.mallocgc+667>  0000000000000202
runtime.throw(0x4c15568, 0x39)
	/usr/local/Cellar/go/1.15.8/libexec/src/runtime/panic.go:1116 +0x72
runtime.sigNotOnStack(0x10)
	/usr/local/Cellar/go/1.15.8/libexec/src/runtime/signal_unix.go:926 +0x85
runtime.adjustSignalStack(0xc000000010, 0x4e8aea0, 0xc000127760, 0x0)
	/usr/local/Cellar/go/1.15.8/libexec/src/runtime/signal_unix.go:516 +0x19b
runtime.sigtrampgo(0x10, 0xc000127c28, 0xc000127c90)
	/usr/local/Cellar/go/1.15.8/libexec/src/runtime/signal_unix.go:461 +0x171
runtime: unexpected return pc for runtime.sigtramp called from 0xc000127c28
stack: frame={sp:0xc0001277b0, fp:0xc0001277c0} stack=[0xc00011f6e0,0xc000127ae0)
000000c0001276b0:  000000c0001276d0  0000000004049665 <runtime.sigNotOnStack+133>
000000c0001276c0:  0000000004c15568  0000000000000039
000000c0001276d0:  000000c000127728  00000000040483db <runtime.adjustSignalStack+411>
000000c0001276e0:  0000000000000010  000000c0001276f8
000000c0001276f0:  000000c000127738  0000000008c22000
000000c000127700:  0000000000010000  0000000000000001
000000c000127710:  000000c00010a330  0000000004c15c30
000000c000127720:  0000000000000000  000000c0001277a0
000000c000127730:  0000000004048131 <runtime.sigtrampgo+369>  000000c000000010
000000c000127740:  0000000004e8aea0  000000c000127760
000000c000127750:  0000000000000000  0000000000000000
000000c000127760:  0000000000000000  0000000000000000
000000c000127770:  0000000000000000  0000000000000000
000000c000127780:  0000000000000000  000000c000000180
000000c000127790:  000000c000127c28  000000c000127c90
000000c0001277a0:  000000c0001277f0  0000000004067db3 <runtime.sigtramp+51>
000000c0001277b0: <0000000000000010 !000000c000127c28
000000c0001277c0: >000000c000127c90  000000c000127c90
000000c0001277d0:  d1560bb8e9a711de  000000000000013e
000000c0001277e0:  000000000000013d  0000000000000200
000000c0001277f0:  000000c000127800  00007fff6c4b05fd
000000c000127800:  000000c000127dd8  0000000000000000
000000c000127810:  0000000000000000  0000000000000000
000000c000127820:  00000000000000de  0000000037140000
000000c000127830:  000000000600a318  0000000004e8aea0
000000c000127840:  000000c000000180  0000000000000008
000000c000127850:  0000000006000108  0000000000000000
000000c000127860:  000000c000127dd8  000000c000127d48
000000c000127870:  0000000004beb8e0  0000000000003001
000000c000127880:  0000000000000018  0000000000000000
000000c000127890:  ffffffffffffffff  000000000000013e
000000c0001278a0:  000000000000013d  0000000000000200
000000c0001278b0:  000000000400ea3b <runtime.mallocgc+667>  0000000000000202
runtime.sigtramp(0xc000127c90, 0xc000127c90, 0xd1560bb8e9a711de, 0x13e, 0x13d, 0x200, 0xc000127800, 0x7fff6c4b05fd, 0xc000127dd8, 0x0, ...)
	/usr/local/Cellar/go/1.15.8/libexec/src/runtime/sys_darwin_amd64.s:229 +0x33

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
	/usr/local/Cellar/go/1.15.8/libexec/src/runtime/asm_amd64.s:1374 +0x1 fp=0xc000066fe8 sp=0xc000066fe0 pc=0x4066481

goroutine 1 [running]:
	goroutine running on other thread; stack unavailable
exit status 2

I'm running go1.15.8 after I found the other issues related to older versions (<1.14.11, I think).

One other data point/question...

I've found that if a Go-defined function is called and panics before the unreachable instruction is executed, I still run into the same crash. For example, here's the WAT:

		(import "" "f2" (func $f2))
		(func (export "f1")
			(call $f2)
			(unreachable)))

In this case, the Go-defined function "f2" just calls panic().

I'm on macOS 10.15.7 in case that helps.

Would rewriting my Go-defined functions to use Traps instead of panicking help at all?

Memory leak involving instances and WrapFunc (due to cycle?)

Hello!

I'm running into a memory leak in v0.22.0 after picking up the fix for #42. Here's a simple program that reproduces it:

package main

import (
	"runtime"

	"github.com/bytecodealliance/wasmtime-go"
)

type X struct {
	instance *wasmtime.Instance
}

func (x *X) F() {

}

func main() {

	bs, err := wasmtime.Wat2Wasm(`
	(module
	  (import "" "hello" (func $hello))
	  (func (export "run")
		(call $hello))
	)
  `)
	check(err)

	for {

		x := &X{}

		store := wasmtime.NewStore(wasmtime.NewEngine())
		imports := []*wasmtime.Extern{wasmtime.WrapFunc(store, x.F).AsExtern()}
		module, err := wasmtime.NewModule(store.Engine, bs)
		check(err)

		instance, err := wasmtime.NewInstance(store, module, imports)
		check(err)

		x.instance = instance

		runtime.GC()
	}
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}

This is a extension of the example from #42. The important difference is that the function passed to WrapFunc closes over the Instance because it's a member function of x. I think this creates a cycle that ultimately prevents the GC from calling the Instance finalizer.

I added some print statements into instance.go and func.go and confirmed that:

  • The instance finalizer is never called
  • The goFinalizeWrap function is never called and gWrapMap grows indefinitely

Unable to install on "Scientific linux" machines

Hey, I am getting continuously this error on 5 different machines at my university when I try to install the wasmtime package:

[2021-02-01 18:31:51] user@pitter1:~/Practice$ go get -u github.com/bytecodealliance/[email protected]
# github.com/bytecodealliance/wasmtime-go
/tmp/go-build478880268/b001/_x002.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x003.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x004.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x005.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x006.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x007.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x008.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x009.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x010.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x011.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x012.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x013.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x014.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x015.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x016.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x017.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x018.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x019.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x020.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x021.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x022.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x023.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x024.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x025.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x026.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x027.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x028.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x029.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: multiple definition of `assertions'
/tmp/go-build478880268/b001/_x001.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: first defined here
/tmp/go-build478880268/b001/_x001.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: undefined reference to `static_assert'
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:31: undefined reference to `static_assert'
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:32: undefined reference to `static_assert'
/tmp/go-build478880268/b001/_x002.o: In function `assertions':
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:30: undefined reference to `static_assert'
../go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:31: undefined reference to `static_assert'
/tmp/go-build478880268/b001/_x002.o:/home/stud/user/go/pkg/mod/github.com/bytecodealliance/[email protected]/build/include/wasm.h:32: more undefined references to `static_assert' follow

The machines are using "Scientific Linux 7.3", and gcc: 4.8.5 (Red Hat 4.8.5-28).
I am sorry in advance if this problem is very basic, I just cannot wrap my head around it. Any idea how to solve this?

Windows support

Hello, I notice that currently this repo just support Linux&macOS, not windows because of gcc.

In my experience, mingw64(msys2)'s gcc works well while staticly compiling c lib for go. So is it possible to add windows support for wasmtime-go based on mingw64?

I'm new to wasmtime, and I don't know whether it supports windows. If it possible, I think I could have a try.

Integrate wasmtime-go into gVisor

Hi,

I made a simple POC to integrate wasmtime-go into gVisor.
Please see the following link as reference:
google/gvisor#5811

gVisor is a user space kernel. Integrating wasmtime-go into gVisor has 2 obvious advantages:
1, Can meet the requirements of OCI
2, Can directly use the syscall/FS provided by gVisor in the implementation of WASI

Can you give some comments? And do you think it's a good idea? I want to apply this combination to serverless scenarios.

Thanks.

How do I recreate the wasmtime CLI?

Iโ€™d like to execute my WASM module just like I do via the command line: wasmtime hello.wasm. My module can read from stdin and wrote to stdout.

How do I use the wasmtime-go package in a similar way?

How to set resource limit in wasmtime-go?

1. background

In my case, i want to limit the max memory that the *.wasm file can use, if it reached the limit, it can crash by OOM.

it's better for me to limit both stack and heap memory.

2. what i have found

In wasmtime, which is written by rust, i found some api to limit the resource:

cpu limit : https://docs.rs/wasmtime/0.29.0/wasmtime/struct.Config.html#method.consume_fuel
stack limit: https://docs.rs/wasmtime/0.29.0/wasmtime/struct.Config.html#method.consume_fuel
memory limit: https://docs.rs/wasmtime/0.29.0/wasmtime/struct.Config.html#method.consume_fuel

these features are so cool and meet my needs, i also found a project named lunatic, it build on wasmtime and allow users to set resource limit as the doc said:

image

3. my question

my host environment is written by golang, so i want to use wasmtime-go to load and run wasm instance, i know this project uses CGO to consume the C API of the Wasmtime project, but i can't find how to set resource limit in wasmtime-go API.

any ideas about this?

Proposal: Wasmtime 1.0

I wanted to raise awareness in this repository about the proposal for Wasmtime to become 1.0. If others are watching just this repository and are interested to learn what 1.0 would mean for Wasmtime and this embedding, feel free to read over the RFC and leave comments!

No API to manipulate table entries

The table API looks pretty much as a placeholder now, one can't do anything useful with it:

type Table
func (t *Table) AsExtern() *Extern
func (t *Table) Size() uint32
func (t *Table) Type() *TableType

The Rust API is actually useful. Examples of missing methods:

pub fn get(&self, index: u32) -> Option<Val>

pub fn set(&self, index: u32, val: Val) -> Result<()>

pub fn grow(&self, delta: u32, init: Val) -> Result<u32>

pub fn copy(
    dst_table: &Table,
    dst_index: u32,
    src_table: &Table,
    src_index: u32,
    len: u32
) -> Result<()>

Error building on macOS

Revision 542c2ac introduced a call to readlink(1) in ci/local.sh that is not compatible with the macOS readlink.
The script produces the following error when executed under macOS:

readlink: illegal option -- f
usage: readlink [-n] [file ...]
Missing libwasmtime.a. Did you `cargo build -p wasmtime-c-api`?

How do I create a trap with a custom message from a NewFunc?

Adjusting the example of #57, I found that if I create a trap like this:

package main

import (
	"runtime"

	"github.com/bytecodealliance/wasmtime-go"
)

func main() {
	bs, err := wasmtime.Wat2Wasm(`
	(module
	  (import "" "hello" (func $hello))
	  (func (export "run")
		(call $hello))
	)
  `)
	check(err)

	for {
		store := wasmtime.NewStore(wasmtime.NewEngine())
		f := wasmtime.NewFunc(store, wasmtime.NewFuncType(nil, nil),
			func(*wasmtime.Caller, []wasmtime.Val) ([]wasmtime.Val, *wasmtime.Trap) {
				return nil, wasmtime.NewTrap(store, "trap")
			})
		imports := []*wasmtime.Extern{f.AsExtern()}
		module, err := wasmtime.NewModule(store.Engine, bs)
		check(err)

		_, err = wasmtime.NewInstance(store, module, imports)
		check(err)

		runtime.GC()
	}
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}

we'll end up leaking memory because the store is closed over in NewFunc (I think). The same isn't the case when changing the crucial bits to this,

		store := wasmtime.NewStore(wasmtime.NewEngine())
		t := wasmtime.NewTrap(store, "trap")
		f := wasmtime.NewFunc(store, wasmtime.NewFuncType(nil, nil),
			func(*wasmtime.Caller, []wasmtime.Val) ([]wasmtime.Val, *wasmtime.Trap) {
				return nil, t
			})

...but then I don't see a way to adjust the trap's message. Is that how traps were intended to be used -- having a static message, and requiring some other means to convey extra information? (Which means would that be, typically?)

Thanks for your time! ๐Ÿ˜ƒ

unable to instantiate wasm instance due to "incompatible import type" error

Hey, I am having an issue instantiating a wasm module due to an import error. The code I am using is here: https://github.com/noot/go-wasmtime-test/blob/master/main.go

the error message I get is the following:

$ go run main.go storage.go 
panic: Failed to link module

Caused by:
    Link error: env/ext_blake2_256: incompatible import type: exported function with signature (i64 vmctx, i64, i64) system_v incompatible with function import with signature (i64 vmctx, i64, i32, i32, i32) system_v

goroutine 1 [running]:
main.check(...)
	/home/elizabeth/go/src/github.com/ChainSafe/go-wasmer-test/main.go:211
main.main()
	/home/elizabeth/go/src/github.com/ChainSafe/go-wasmer-test/main.go:197 +0x127d
exit status 2

however, I'm not sure why this is happening, since I'm not importing any functions with the signature (i64 vmctx, i64, i32, i32, i32), and the ext_blake2_256 function doesn't have (i64 vmctx, i64, i64) as its parameter type. also, it's unclear to me how wasmtime is matching the imported go functions to the exports declared by the wasm module, since wasmtime.WrapFunc doesn't take a name. if it is matching by parameters, that might be causing issues in the case of multiple imports with the same parameters. maybe I am missing something in how the functions are being matched.

if it helps, the WAT for the imports I am using is the following:

  (type $t0 (func (param i32 i32 i32) (result i32)))
  (type $t1 (func (param i32 i32) (result i32)))
  (type $t2 (func (param i32 i32 i32)))
  (type $t3 (func (param i32 i32 i32 i32)))
  (type $t4 (func (param i32)))
  (type $t5 (func (param i32 i32)))
  (type $t6 (func (param i32 i32 i32 i32 i32)))
  (type $t7 (func (param i32) (result i64)))
  (type $t8 (func (param i32 i32 i32 i32 i32) (result i32)))
  (type $t9 (func (param i32 i32 i32 i32 i32 i32) (result i32)))
  (type $t10 (func (param i32 i32 i32 i32 i32 i32 i32 i32) (result i32)))
  (type $t11 (func (param i64)))
  (type $t12 (func (result i32)))
  (type $t13 (func (param i32 i32 i32 i32) (result i32)))
  (type $t14 (func (param i32 i32 i32 i32 i32 i32 i32) (result i32)))
  (type $t15 (func (param i32) (result i32)))
  (type $t16 (func (param i32 i32 i32 i32 i32 i32)))
  (type $t17 (func (param i32 i32) (result i64)))
  (type $t18 (func))
  (type $t19 (func (param i64 i32 i32) (result i32)))
  (type $t20 (func (param i32 i64 i64)))
  (type $t21 (func (param i32 i32 i64 i64)))
  (type $t22 (func (param i32 i32 i64 i64 i32 i32)))
  (type $t23 (func (param i32 i32 i64 i64 i32)))
  (type $t24 (func (param i32 i32 i32 i64 i64)))
  (type $t25 (func (param i32 i64 i64 i64)))
  (type $t26 (func (param i32 i32 i64 i64 i32 i32 i32)))
  (type $t27 (func (param i32 i32 i32 i32 i32 i64 i64 i32)))
  (type $t28 (func (param i32 i32 i32 i64 i64 i32 i32)))
  (type $t29 (func (param i32 i32 i32 i64 i64 i32)))
  (type $t30 (func (param i32 i32 i32 i32) (result i64)))
  (type $t31 (func (param i32 i64 i64 i32 i32 i32 i32)))
  (type $t32 (func (param i32 i32 i32 i64 i64 i64 i32)))
  (type $t33 (func (param i32 i32 i32 i32 i64 i64)))
  (type $t34 (func (param i64 i32)))
  (type $t35 (func (param i32 i64 i64 i64 i64 i64 i64)))
  (type $t36 (func (param i64 i64 i64 i64 i64 i64 i64 i64) (result i32)))
  (type $t37 (func (result i64)))
  (type $t38 (func (param i32 i64 i64 i32)))
  (type $t39 (func (param i32 i64 i64 i64 i64)))
  (type $t40 (func (param i32 i64 i64 i64 i64 i32)))
  (import "env" "ext_blake2_256" (func $ext_blake2_256 (type $t2)))
  (import "env" "ext_twox_128" (func $ext_twox_128 (type $t2)))
  (import "env" "ext_clear_storage" (func $ext_clear_storage (type $t5)))
  (import "env" "ext_set_storage" (func $ext_set_storage (type $t3)))
  (import "env" "ext_get_allocated_storage" (func $ext_get_allocated_storage (type $t0)))
  (import "env" "ext_get_storage_into" (func $ext_get_storage_into (type $t8)))
  (import "env" "ext_kill_child_storage" (func $ext_kill_child_storage (type $t5)))
  (import "env" "ext_sandbox_memory_new" (func $ext_sandbox_memory_new (type $t1)))
  (import "env" "ext_sandbox_memory_teardown" (func $ext_sandbox_memory_teardown (type $t4)))
  (import "env" "ext_sandbox_instantiate" (func $ext_sandbox_instantiate (type $t9)))
  (import "env" "ext_sandbox_invoke" (func $ext_sandbox_invoke (type $t10)))
  (import "env" "ext_sandbox_instance_teardown" (func $ext_sandbox_instance_teardown (type $t4)))
  (import "env" "ext_print_utf8" (func $ext_print_utf8 (type $t5)))
  (import "env" "ext_print_hex" (func $ext_print_hex (type $t5)))
  (import "env" "ext_print_num" (func $ext_print_num (type $t11)))
  (import "env" "ext_is_validator" (func $ext_is_validator (type $t12)))
  (import "env" "ext_local_storage_get" (func $ext_local_storage_get (type $t13)))
  (import "env" "ext_local_storage_compare_and_set" (func $ext_local_storage_compare_and_set (type $t14)))
  (import "env" "ext_sr25519_public_keys" (func $ext_sr25519_public_keys (type $t1)))
  (import "env" "ext_network_state" (func $ext_network_state (type $t15)))
  (import "env" "ext_sr25519_sign" (func $ext_sr25519_sign (type $t8)))
  (import "env" "ext_submit_transaction" (func $ext_submit_transaction (type $t1)))
  (import "env" "ext_local_storage_set" (func $ext_local_storage_set (type $t6)))
  (import "env" "ext_get_allocated_child_storage" (func $ext_get_allocated_child_storage (type $t8)))
  (import "env" "ext_ed25519_generate" (func $ext_ed25519_generate (type $t3)))
  (import "env" "ext_sr25519_generate" (func $ext_sr25519_generate (type $t3)))
  (import "env" "ext_child_storage_root" (func $ext_child_storage_root (type $t0)))
  (import "env" "ext_clear_prefix" (func $ext_clear_prefix (type $t5)))
  (import "env" "ext_storage_root" (func $ext_storage_root (type $t4)))
  (import "env" "ext_storage_changes_root" (func $ext_storage_changes_root (type $t0)))
  (import "env" "ext_clear_child_storage" (func $ext_clear_child_storage (type $t3)))
  (import "env" "ext_set_child_storage" (func $ext_set_child_storage (type $t16)))
  (import "env" "ext_secp256k1_ecdsa_recover_compressed" (func $ext_secp256k1_ecdsa_recover_compressed (type $t0)))
  (import "env" "ext_ed25519_verify" (func $ext_ed25519_verify (type $t13)))
  (import "env" "ext_sr25519_verify" (func $ext_sr25519_verify (type $t13)))
  (import "env" "ext_sandbox_memory_get" (func $ext_sandbox_memory_get (type $t13)))
  (import "env" "ext_sandbox_memory_set" (func $ext_sandbox_memory_set (type $t13)))
  (import "env" "ext_blake2_256_enumerated_trie_root" (func $ext_blake2_256_enumerated_trie_root (type $t3)))
  (import "env" "ext_malloc" (func $ext_malloc (type $t15)))
  (import "env" "ext_free" (func $ext_free (type $t4)))
  (import "env" "ext_twox_64" (func $ext_twox_64 (type $t2)))
  (import "env" "ext_log" (func $ext_log (type $t6)))

any help is much appreciated! thanks :)

Segfault on macOS

CI has been segfaulting for some time on macOS and I've recently tried to reduce this. I can pretty reliably reproduce this locally as well. So far I've managed to shrink this to:

package main

// #include <wasm.h>
//
// static wasm_trap_t* myTrampoline(
//    const wasm_val_t *args,
//    wasm_val_t *results
// ) {
//   return NULL;
// }
//
// void my_run() {
//   wasm_engine_t *engine = wasm_engine_new();
//   wasm_store_t *store = wasm_store_new(engine);
//   wasm_functype_t *ty = wasm_functype_new_0_0();
//   wasm_func_t *func = wasm_func_new(store, ty, myTrampoline);
//   wasm_func_call(func, NULL, NULL);
// }
import "C"
import "runtime"

func main() {
	C.my_run()
	runtime.GC()
}

When compiled on macOS that will periodically segfault in the garbage collector. I've got a script which runs it in a loop and it can take up to ~2k runs to get the segfault, but it typically comes relatively quickly if you're running it in a loop.

I'm not really sure what to do about this myself. That seems like a bug in the Go runtime? I don't feel comfortable reporting this upstream until it's reduced further (e.g. not depending on libwasmtime.a). Trivial reductions of libwasmtime.a don't exhibit the same segfault so there's something "interesting" going on in the Rust code which seems like it's affecting Go. I'm 90% certain though that the C code above doesn't actually have any segfaults or corruption in it, so I'm not really sure how to fix this unfortunately...

Can host function be imported by name?

From the example and manual, it seems impossible to specify a namespace & a name for the host function to be imported, thus I can only import them by index in the wasm code:

item := wasmtime.WrapFunc(store, func() {
    fmt.Println("Hello from Go!")
})

// Next up we instantiate a module which is where we link in all our
// imports. We've got one import so we pass that in here.
instance, err := wasmtime.NewInstance(store,module, []*wasmtime.Extern{item.AsExtern()})

Is there a way to import them by name? for example, like what wasmer does:

hostFunc := wasmer.NewFunction(
	store,
	wasmer.NewFunctionType(wasmer.NewValueTypes(), wasmer.NewValueTypes()),
	func(args []wasmer.Value) ([]wasmer.Value, error) {
                fmt.Println("Hello from Go!")
		return nil, nil
	},
)
importObject.Register("foo", map[string]wasmer.IntoExtern{"bar":  hostFunc})
instance, err := wasmer.NewInstance(module, importObject)

Add SetStdout SetStdin

I saw that I cannot easily convert the string path in SetStdoutFile(path string) to the io.ReadWriter on wasmtime-go, so this is a suggestion to wasmtime.

io.ReadWriter is an interface which implemented by os.File and bytes.Buffer. With an io.ReadWriter as the parameter for WASI config, golang can operate its favor bytes without filesystem-level io, which means the WASI call will be more easy safe and stable.

buf := bytes.NewBuffer(nil)
config := wasmtime.NewWasiConfig()	
config.SetStdin(buf)
config.SetStdout(buf)

// then instaniate the wasi with the config

go func(){
	b, err buf.ReadBytes('\n')
	// handle this
}()
go instance.GetExport("_start").Func().Call()
// now intance request a stdin
buf.Write("continue exec")

Support bazel

Nowadays, bazel is a welcoming build tool for big go projects, for example, the ETH 2.0 daemon https://github.com/prysmaticlabs/prysm. And the wasmer's go-ext-wasm is also using bazel.

I tried to add the bazel support for wasmtime-go according to wasmer's practice , but failed since wasmer chooses putting compiled binary lib in the repo. I also tried to download the binaries in bazel's style, but failed on matching platform matric with its select() func bazelbuild/bazel#11655.

So if would be great that you can help implement this.

unable to install/compile under Windows 10

It reports [....]/[email protected]/build/windows-x86_64/libwasmtime.a(zdict.o):zdict.c:(.text$ZDICT_analyzePos+0x5c9): undefined reference to '__imp___acrt_iob_func' and similar.

It seems it is binary dependency problem with libraries used by CGO, probably VS related. Any idea how to solve it?

Failed to compile under docker golang:alpine

Step 10/11 : RUN GOPROXY=$GOPROXY go test ./...
 ---> Running in 11eab791155a
go: downloading github.com/bytecodealliance/wasmtime-go v0.17.0
# github.com/bytecodealliance/wasmtime-go
/usr/lib/gcc/x86_64-alpine-linux-musl/9.2.0/../../../../x86_64-alpine-linux-musl/bin/ld: /go/pkg/mod/github.com/bytecodealliance/[email protected]/build/linux-x86_64/libwasmtime.a(std-3859b7e52a41a8fd.std.1o062trz-cgu.0.rcgu.o): in function `std::sys::unix::net::on_resolver_failure':
/rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd//src/libstd/sys/unix/net.rs:377: undefined reference to `__res_init'
collect2: error: ld returned 1 exit status

Dockerfile

FROM golang:alpine

ARG goproxy=https://goproxy.io
ARG in_china=0
ENV GOPROXY ${goproxy}

COPY . /build
WORKDIR /build

# RUN apk add build-base
RUN apk add --no-cache make gcc musl-dev linux-headers git
RUN GOPROXY=$GOPROXY go test ./...

It seems an upstream issue between wasmtime and alpine(musl)?

How can I use WASI to open a file?

Hi,

maybe there is some documentation somewhere but I just cannot figure out how to run a WASM binary from Go with wasmtime.

I compiled a Rust program to wasm with cargo wasi build --release. I want to call a method from Golang and wrote the following simple example:

package main

import (
	"fmt"
	"github.com/bytecodealliance/wasmtime-go"
)

func main() {
	engine := wasmtime.NewEngine()
	store := wasmtime.NewStore(engine)

	linker := wasmtime.NewLinker(store)

	module, err := wasmtime.NewModuleFromFile(engine, "../target/wasm32-wasi/release/bench.wasm")
	check(err)

	for _, v := range module.Imports() {
		fmt.Printf("%v ", v.Name())
	}

	wasiConfig := wasmtime.NewWasiConfig()
	wasiConfig.InheritEnv()
	wasiConfig.PreopenDir(".", ".")
	wasi, err := wasmtime.NewWasiInstance(store, wasiConfig, "wasi_unstable")
	check(err)

	err = linker.DefineWasi(wasi)
	check(err)

	instance, err := linker.Instantiate(module)
	check(err)

	nom := instance.GetExport("run_nom").Func()
	_, err = nom.Call()
	check(err)
}

func check(err error) {
	if err != nil {
        panic(err)
	}
}

It prints the required imports fd_close fd_filestat_get fd_read fd_write path_open proc_exit environ_sizes_get environ_get and the fails with the error panic: unknown import: wasi_snapshot_preview1::fd_close has not been defined. Shouldn't PreopenDir define fd_close?

How can I define the imports?

Thanks a lot ๐Ÿ™‚

PS: I am happy to contribute with an example in the docs.

Wrong panic message being propagated

The panic handler that handles panics coming from calls to hosted functions saves any panic that occurred in data.lastPanic (func.go line 114) ready for propagation across the Wasm code to where the Wasm code was called. Then the code continues executing the Wasm code, but if the Wasm code does not hit the interrupt checkpoint immediately after that the Wasm code could (and does, in my case) trigger another panic. This causes lastPanic to be overwritten with this second panic message, and this could go on until finally the interrupt checkpoint is hit. The end result is that the wrong panic message is propagated to the code that called the Wasm code.
I spent hours trying to figure out why it reported an error after it should have panicked, only to find this out when digging in deep.
The fix could probably simply be not to overwrite data.lastPanic if it isn't nil, but I don't know if that could influence anything else.
I worked around this problem by catching the panic before WasmTime and propagating it myself, but this should probably be fixed to help others.

Profiling from macos?

I've been going through the docs on profiling wasm executions using wasmtime, and they state that there's perf and vtune.

On macos, I don't think running perf is entirely easy (see docker/for-mac#5500, since I don't control he VM host's kernel version, it would be best if the perf package came from the same source...).

However, it seems that vtune supports macos. But, I find that it's not an option for wasmtime-go -- Is there an underlying reason for this?

Thanks!

Trap's message "note" is a bit misleading

Without any env vars set, I get this:

wasm trap: out of bounds memory access
wasm backtrace:
    0: 0x4f3d - <unknown>!opa_value_length
    1: 0x2528 - <unknown>!opa_json_writer_emit_set_literal
    2: 0x22c7 - <unknown>!opa_json_writer_emit_value
    3: 0x27bc - <unknown>!opa_json_writer_write
    4: 0x28f8 - <unknown>!opa_value_dump
    5:  0x791 - <unknown>!opa_eval
note: run with `WASMTIME_BACKTRACE_DETAILS=1` environment variable to display more information

Setting WASMTIME_BACKTRACE_DETAILS=1, I get the same message without the note:

wasm trap: out of bounds memory access
wasm backtrace:
    0: 0x4f3d - <unknown>!opa_value_length
    1: 0x2528 - <unknown>!opa_json_writer_emit_set_literal
    2: 0x22c7 - <unknown>!opa_json_writer_emit_value
    3: 0x27bc - <unknown>!opa_json_writer_write
    4: 0x28f8 - <unknown>!opa_value_dump
    5:  0x791 - <unknown>!opa_eval

Another nitpick is the comment on Message,

wasmtime-go/trap.go

Lines 48 to 49 in ef5be5d

// Message returns the name in the module this export type is exporting
func (t *Trap) Message() string {

doesn't seem quite correct ๐Ÿค”

target aarch64?

Hey there.

It seems like wasmtime has c-api artifacts for aarch64, but there aren't any in wasmtime-go.

I guess there's more to it than adding a line here,

['wasmtime-dev-x86_64-mingw-c-api.zip', 'windows-x86_64'],
-- we'd likely have to do the qemu dance that wasmtime does in the github action here, too?

interrupt triggering SIGILL

๐Ÿ‘‰ main.go, go.sum and go.mod are here

Running go run main.go, iteration 388 gives me

2021/04/27 21:02:57 387: trap: wasm trap: interrupt
wasm backtrace:
    0:   0x21 - <unknown>!<wasm function 0>
SIGILL: illegal instruction
PC=0x33f6001a m=3 sigcode=1
instruction bytes: 0xf 0xb 0x55 0x48 0x89 0xe5 0xff 0xd2 0x48 0x89 0xec 0x5d 0xc3 0x0 0x0 0x0

goroutine 0 [idle]:
runtime: unknown pc 0x33f6001a
stack: frame={sp:0x70000e951a10, fp:0x0} stack=[0x70000e8d2350,0x70000e951f50)
000070000e951910:  0000000000000000  0000000000000000
000070000e951920:  0000000000000000  0000000000000000
000070000e951930:  0000000000000000  0000000000000000
000070000e951940:  0000000000000000  0000000000000000
000070000e951950:  0000000000000000  0000000000000000
000070000e951960:  0000000000000000  0000000000000000
000070000e951970:  0000000000000000  0000000000000000
000070000e951980:  0000000000000000  0000000000000000
000070000e951990:  0000000000000000  0000000000000000
000070000e9519a0:  0000000000000000  0000000000000000
000070000e9519b0:  0000000000000000  0000000000000000
000070000e9519c0:  0000000000000000  0000000000000000
000070000e9519d0:  0000000000000000  0000000000000000
000070000e9519e0:  0000000000000000  0000000000000000
000070000e9519f0:  0000000000000000  0000000000000000
000070000e951a00:  0000000000000000  0000000000000000
000070000e951a10: <000070000e951a20  0000000033f60022
000070000e951a20:  000070000e951b00  00000000047b5ccc
000070000e951a30:  0000000000000000  50878a5e3aac6a03
000070000e951a40:  50878a5e3aac6b33  000070000e951b50
000070000e951a50:  000070000e951a30  000070000e951cd0
000070000e951a60:  00000000043bf9e0  5087fa5e30422dbd
000070000e951a70:  0000000000000000  0000037f00001f80
000070000e951a80:  0000000000000000  0000000000000000
000070000e951a90:  0000000000000000  0000000000000000
000070000e951aa0:  000000c0001de8a0  000000c0001db898
000070000e951ab0:  0000000000000000  000070000e951b18
000070000e951ac0:  0000000005fd3790  000070000e951cd0
000070000e951ad0:  5831d1b433c600b4  000070000e951cd0
000070000e951ae0:  0000000000000008  000070000e951da8
000070000e951af0:  000070000e951d20  000070000e951b50
000070000e951b00:  000070000e951bc0  00000000043bfa9f
runtime: unknown pc 0x33f6001a
stack: frame={sp:0x70000e951a10, fp:0x0} stack=[0x70000e8d2350,0x70000e951f50)
000070000e951910:  0000000000000000  0000000000000000
000070000e951920:  0000000000000000  0000000000000000
000070000e951930:  0000000000000000  0000000000000000
000070000e951940:  0000000000000000  0000000000000000
000070000e951950:  0000000000000000  0000000000000000
000070000e951960:  0000000000000000  0000000000000000
000070000e951970:  0000000000000000  0000000000000000
000070000e951980:  0000000000000000  0000000000000000
000070000e951990:  0000000000000000  0000000000000000
000070000e9519a0:  0000000000000000  0000000000000000
000070000e9519b0:  0000000000000000  0000000000000000
000070000e9519c0:  0000000000000000  0000000000000000
000070000e9519d0:  0000000000000000  0000000000000000
000070000e9519e0:  0000000000000000  0000000000000000
000070000e9519f0:  0000000000000000  0000000000000000
000070000e951a00:  0000000000000000  0000000000000000
000070000e951a10: <000070000e951a20  0000000033f60022
000070000e951a20:  000070000e951b00  00000000047b5ccc
000070000e951a30:  0000000000000000  50878a5e3aac6a03
000070000e951a40:  50878a5e3aac6b33  000070000e951b50
000070000e951a50:  000070000e951a30  000070000e951cd0
000070000e951a60:  00000000043bf9e0  5087fa5e30422dbd
000070000e951a70:  0000000000000000  0000037f00001f80
000070000e951a80:  0000000000000000  0000000000000000
000070000e951a90:  0000000000000000  0000000000000000
000070000e951aa0:  000000c0001de8a0  000000c0001db898
000070000e951ab0:  0000000000000000  000070000e951b18
000070000e951ac0:  0000000005fd3790  000070000e951cd0
000070000e951ad0:  5831d1b433c600b4  000070000e951cd0
000070000e951ae0:  0000000000000008  000070000e951da8
000070000e951af0:  000070000e951d20  000070000e951b50
000070000e951b00:  000070000e951bc0  00000000043bfa9f

goroutine 1 [syscall]:
runtime.cgocall(0x40b7740, 0xc00019bcf0, 0xc0001de8a0)
        /nix/store/2dgrrcr9z6571yygbzwcds3ss1vid4sk-go-1.16/share/go/src/runtime/cgocall.go:154 +0x5b fp=0xc00019bcc0 sp=0xc00019bc88 pc=0x400407b
github.com/bytecodealliance/wasmtime-go._Cfunc_go_wasmtime_func_call(0x5fd4db0, 0xc0001de890, 0xc0001de8a0, 0xc0001db898, 0x0)
        _cgo_gotypes.go:715 +0x49 fp=0xc00019bcf0 sp=0xc00019bcc0 pc=0x40abf29
github.com/bytecodealliance/wasmtime-go.(*Func).Call.func3.1(0xc0000a5c60, 0xc0001de890, 0xc0001de8a0, 0xc0001db898, 0xc38b091e922abf01)
        /Users/stephan/go/pkg/mod/github.com/bytecodealliance/[email protected]/func.go:505 +0x117 fp=0xc00019bd30 sp=0xc00019bcf0 pc=0x40b44f7
github.com/bytecodealliance/wasmtime-go.(*Func).Call.func3(0xc0001db898)
        /Users/stephan/go/pkg/mod/github.com/bytecodealliance/[email protected]/func.go:505 +0x4f fp=0xc00019bd70 sp=0xc00019bd30 pc=0x40b456f
github.com/bytecodealliance/wasmtime-go.enterWasm(0xc0000b8900, 0xc00019be98, 0x0)
        /Users/stephan/go/pkg/mod/github.com/bytecodealliance/[email protected]/func.go:589 +0xf0 fp=0xc00019bdd0 sp=0xc00019bd70 pc=0x40b0630
github.com/bytecodealliance/wasmtime-go.(*Func).Call(0xc0000a5c60, 0x0, 0x0, 0x0, 0x0, 0xc0000b0d50, 0x0, 0x0)
        /Users/stephan/go/pkg/mod/github.com/bytecodealliance/[email protected]/func.go:500 +0x27d fp=0xc00019bed0 sp=0xc00019bdd0 pc=0x40aff7d
main.main()
        /Users/stephan/Scratch/wasmtime/sigill/main.go:35 +0x1f4 fp=0xc00019bf88 sp=0xc00019bed0 pc=0x40b6954
runtime.main()
        /nix/store/2dgrrcr9z6571yygbzwcds3ss1vid4sk-go-1.16/share/go/src/runtime/proc.go:225 +0x256 fp=0xc00019bfe0 sp=0xc00019bf88 pc=0x4037356
runtime.goexit()
        /nix/store/2dgrrcr9z6571yygbzwcds3ss1vid4sk-go-1.16/share/go/src/runtime/asm_amd64.s:1371 +0x1 fp=0xc00019bfe8 sp=0xc00019bfe0 pc=0x4066d21

rax    0xffffffffffff7fff
rbx    0x0
rcx    0x8
rdx    0x33f60000
rdi    0xffffffffffff7fff
rsi    0x5fd30b0
rbp    0x70000e951a10
rsp    0x70000e951a10
r8     0x33f6001c
r9     0xc0001db898
r10    0xc0001de8a0
r11    0x0
r12    0x70000e951b50
r13    0x70000e951a30
r14    0x70000e951cd0
r15    0x43bf9e0
rip    0x33f6001a
rflags 0x10246
cs     0x2b
fs     0x0
gs     0x0
exit status 2

Some environment information,

  • macos big sur 11.2.3
  • go version go1.16 darwin/amd64

I'll gladly supply more information, or do some guided poking -- I'm afraid I don't really know where to start. ๐Ÿ˜…


Follow-up to #60.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.