Skip to content

Commit 9848a00

Browse files
authored
Release value memory on context close (#78)
* 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
1 parent 3605835 commit 9848a00

File tree

7 files changed

+145
-63
lines changed

7 files changed

+145
-63
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
## [v0.5.1] - 2021-02-19
10+
11+
### Fixed
12+
- Memory being held by Values after the associated Context is closed
13+
914
## [v0.5.0] - 2021-02-08
1015

1116
### Added

context.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,11 @@ func (c *Context) RunScript(source string, origin string) (*Value, error) {
116116
func (c *Context) Global() *Object {
117117
valPtr := C.ContextGlobal(c.ptr)
118118
v := &Value{valPtr, c}
119-
runtime.SetFinalizer(v, (*Value).finalizer)
120119
return &Object{v}
121120
}
122121

123122
// Close will dispose the context and free the memory.
123+
// Access to any values assosiated with the context after calling Close may panic.
124124
func (c *Context) Close() {
125125
c.finalizer()
126126
}
@@ -165,13 +165,17 @@ func getContext(ref int) *Context {
165165
return r.ctx
166166
}
167167

168+
//export goContext
169+
func goContext(ref int) C.ContextPtr {
170+
ctx := getContext(ref)
171+
return ctx.ptr
172+
}
173+
168174
func getValue(ctx *Context, rtn C.RtnValue) *Value {
169175
if rtn.value == nil {
170176
return nil
171177
}
172-
v := &Value{rtn.value, ctx}
173-
runtime.SetFinalizer(v, (*Value).finalizer)
174-
return v
178+
return &Value{rtn.value, ctx}
175179
}
176180

177181
func getError(rtn C.RtnValue) error {

context_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,23 @@ func TestContextRegistry(t *testing.T) {
9292
}
9393
}
9494

95+
func TestMemoryLeak(t *testing.T) {
96+
t.Parallel()
97+
98+
iso, _ := v8go.NewIsolate()
99+
100+
for i := 0; i < 6000; i++ {
101+
ctx, _ := v8go.NewContext(iso)
102+
obj := ctx.Global()
103+
_ = obj.String()
104+
_, _ = ctx.RunScript("2", "")
105+
ctx.Close()
106+
}
107+
if n := iso.GetHeapStatistics().NumberOfNativeContexts; n >= 6000 {
108+
t.Errorf("Context not being GC'd, got %d native contexts", n)
109+
}
110+
}
111+
95112
func BenchmarkContext(b *testing.B) {
96113
b.ReportAllocs()
97114
vm, _ := v8go.NewIsolate()

function_template.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ func goFunctionCallback(ctxref int, cbref int, args *C.ValuePtr, argsCount int)
7070
argv := (*[1 << 30]C.ValuePtr)(unsafe.Pointer(args))[:argsCount:argsCount]
7171
for i, v := range argv {
7272
val := &Value{ptr: v}
73-
runtime.SetFinalizer(val, (*Value).finalizer)
7473
info.args[i] = val
7574
}
7675

0 commit comments

Comments
 (0)