From 821be277b396341a217f16a08eb66457a1283419 Mon Sep 17 00:00:00 2001 From: Paul van Brouwershaven Date: Thu, 3 Mar 2016 14:44:33 -0500 Subject: [PATCH] Add Dispose() Fixes #36, #37 --- worker.go | 26 ++++++++++++++++++++------ worker_test.go | 22 ++++++++++++++++++++++ 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/worker.go b/worker.go index e288096..2009286 100644 --- a/worker.go +++ b/worker.go @@ -45,6 +45,7 @@ type worker struct { // This is a golang wrapper around a single V8 Isolate. type Worker struct { *worker + disposed bool } // Return the V8 version E.G. "4.3.59" @@ -93,18 +94,31 @@ func New(cb ReceiveMessageCallback, sync_cb ReceiveSyncMessageCallback) *Worker w.cWorker = C.worker_new(C.int(w.tableIndex)) - externalWorker := &Worker{worker: w} + externalWorker := &Worker{ + worker: w, + disposed: false, + } runtime.SetFinalizer(externalWorker, func(final_worker *Worker) { - workerTableLock.Lock() - w := final_worker.worker - delete(workerTable, w.tableIndex) - workerTableLock.Unlock() - C.worker_dispose(w.cWorker) + final_worker.Dispose() }) return externalWorker } +// Forcefully frees up memory associated with worker. +// GC will also free up worker memory so calling this isn't strictly necessary. +func (w *Worker) Dispose() { + if w.disposed { + panic("worker already disposed") + } + w.disposed = true + workerTableLock.Lock() + internalWorker := w.worker + delete(workerTable, internalWorker.tableIndex) + workerTableLock.Unlock() + C.worker_dispose(internalWorker.cWorker) +} + // Load and executes a javascript file with the filename specified by // scriptName and the contents of the file specified by the param code. func (w *Worker) Load(scriptName string, code string) error { diff --git a/worker_test.go b/worker_test.go index 1170572..19146ce 100644 --- a/worker_test.go +++ b/worker_test.go @@ -195,3 +195,25 @@ func TestWorkerBreaking(t *testing.T) { worker.Load("forever.js", ` while (true) { ; } `) } + +func TestTightCreateLoop(t *testing.T) { + println("create 3000 workers in tight loop to see if we get OOM") + for i := 0; i < 3000; i++ { + runSimpleWorker(t) + } + println("success") +} + +func runSimpleWorker(t *testing.T) { + w := New(nil, nil) + defer w.Dispose() + + err := w.Load("mytest.js", ` + // Do something + var something = "Simple JavaScript"; + `) + + if err != nil { + t.Fatal(err) + } +}