Skip to content

Commit

Permalink
Release value memory on context close (#78)
Browse files Browse the repository at this point in the history
* Release value memory on context close

* retry test with a larger number of contexts

* no need to re-cast

* Update changelog and release v0.5.1
  • Loading branch information
rogchap authored Feb 19, 2021
1 parent 3605835 commit 9848a00
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 63 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [v0.5.1] - 2021-02-19

### Fixed
- Memory being held by Values after the associated Context is closed

## [v0.5.0] - 2021-02-08

### Added
Expand Down
12 changes: 8 additions & 4 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,11 @@ func (c *Context) RunScript(source string, origin string) (*Value, error) {
func (c *Context) Global() *Object {
valPtr := C.ContextGlobal(c.ptr)
v := &Value{valPtr, c}
runtime.SetFinalizer(v, (*Value).finalizer)
return &Object{v}
}

// Close will dispose the context and free the memory.
// Access to any values assosiated with the context after calling Close may panic.
func (c *Context) Close() {
c.finalizer()
}
Expand Down Expand Up @@ -165,13 +165,17 @@ func getContext(ref int) *Context {
return r.ctx
}

//export goContext
func goContext(ref int) C.ContextPtr {
ctx := getContext(ref)
return ctx.ptr
}

func getValue(ctx *Context, rtn C.RtnValue) *Value {
if rtn.value == nil {
return nil
}
v := &Value{rtn.value, ctx}
runtime.SetFinalizer(v, (*Value).finalizer)
return v
return &Value{rtn.value, ctx}
}

func getError(rtn C.RtnValue) error {
Expand Down
17 changes: 17 additions & 0 deletions context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,23 @@ func TestContextRegistry(t *testing.T) {
}
}

func TestMemoryLeak(t *testing.T) {
t.Parallel()

iso, _ := v8go.NewIsolate()

for i := 0; i < 6000; i++ {
ctx, _ := v8go.NewContext(iso)
obj := ctx.Global()
_ = obj.String()
_, _ = ctx.RunScript("2", "")
ctx.Close()
}
if n := iso.GetHeapStatistics().NumberOfNativeContexts; n >= 6000 {
t.Errorf("Context not being GC'd, got %d native contexts", n)
}
}

func BenchmarkContext(b *testing.B) {
b.ReportAllocs()
vm, _ := v8go.NewIsolate()
Expand Down
1 change: 0 additions & 1 deletion function_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ func goFunctionCallback(ctxref int, cbref int, args *C.ValuePtr, argsCount int)
argv := (*[1 << 30]C.ValuePtr)(unsafe.Pointer(args))[:argsCount:argsCount]
for i, v := range argv {
val := &Value{ptr: v}
runtime.SetFinalizer(val, (*Value).finalizer)
info.args[i] = val
}

Expand Down
Loading

0 comments on commit 9848a00

Please sign in to comment.