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
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:
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: