Skip to content

Commit

Permalink
fix memory leak when using scopes with recursive timers (#227)
Browse files Browse the repository at this point in the history
  • Loading branch information
rochdev authored Aug 13, 2018
1 parent b1e08fd commit 1999ee7
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 6 deletions.
5 changes: 4 additions & 1 deletion src/scope/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@ class Context {
}

link (parent) {
this.unlink()
const oldParent = this._parent

this._parent = parent
this._parent.attach(this)

oldParent && oldParent.detach(this)
}

unlink () {
Expand Down
14 changes: 10 additions & 4 deletions src/scope/context_execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class ContextExecution {
this._active = null
this._count = 0
this._set = []
this._executed = false

if (context) {
context.retain()
Expand Down Expand Up @@ -43,14 +44,17 @@ class ContextExecution {

this._set.splice(index, 1)
this._active = this._set[this._set.length - 1] || null
}

exit () {
if (this._context && !this._active) {
if (this._executed) {
this._bypass()
}
}

exit () {
this._executed = true
this._bypass()
}

attach (child) {
this._children.add(child)
this.retain()
Expand All @@ -76,7 +80,9 @@ class ContextExecution {
}

_bypass () {
this._children.forEach(child => child.link(this._context.parent()))
if (this._context && !this._active) {
this._children.forEach(child => child.link(this._context.parent()))
}
}
}

Expand Down
16 changes: 15 additions & 1 deletion test/leak/scope_manager.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

require('../..').init()
const tracer = require('../..').init()

const test = require('tape')
const profile = require('../profile')
Expand All @@ -12,3 +12,17 @@ test('ScopeManager should destroy executions even if their context is already de
Promise.resolve().then(done)
}
})

test('ScopeManager should not leak when using scopes with recursive timers', t => {
profile(t, operation)

function operation (done) {
const active = tracer.scopeManager().active()

active && active.close()

tracer.scopeManager().activate({})

done()
}
})

0 comments on commit 1999ee7

Please sign in to comment.