Skip to content
This repository has been archived by the owner on May 23, 2024. It is now read-only.

Commit

Permalink
Prevent a very edgy zalgo-related race condition
Browse files Browse the repository at this point in the history
If you start an inflight for the same key that the current cb is
executing on, then you can potentially cause things to be happening in
parallel that should be garanteed to never happen in parallel.
  • Loading branch information
isaacs committed Oct 1, 2014
1 parent f0c2b45 commit 32bc5b6
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 5 deletions.
18 changes: 13 additions & 5 deletions inflight.js
Expand Up @@ -15,11 +15,19 @@ function inflight (key, cb) {
}

function makeres(key) {
return once(function(error, data) {
return once(function RES (error, data) {
var cbs = reqs[key]
delete reqs[key]
cbs.forEach(function(cb) {
cb(error, data)
})
var len = cbs.length
for (var i = 0; i < len; i++) {
cbs[i](error, data)
}
if (cbs.length > len) {
// added more in the interim.
// de-zalgo, just in case, but don't call again.
cbs.splice(0, len)
process.nextTick(RES.bind(this, error, data))
} else {
delete reqs[key]
}
})
}
42 changes: 42 additions & 0 deletions test.js
Expand Up @@ -31,3 +31,45 @@ test('basic', function (t) {

t.notOk(b, 'second should get falsey inflight response')
})

test('timing', function (t) {
var expect = [
'method one',
'start one',
'end one',
'two',
'tick',
'three'
]
var i = 0

function log (m) {
t.equal(m, expect[i], m + ' === ' + expect[i])
++i
if (i === expect.length)
t.end()
}

function method (name, cb) {
log('method ' + name)
process.nextTick(cb)
}

var one = inf('foo', function () {
log('start one')
var three = inf('foo', function () {
log('three')
})
if (three) method('three', three)
log('end one')
})

method('one', one)

var two = inf('foo', function () {
log('two')
})
if (two) method('one', two)

process.nextTick(log.bind(null, 'tick'))
})

0 comments on commit 32bc5b6

Please sign in to comment.