summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolan McMahon <caolan@caolanmcmahon.com>2013-01-31 15:12:16 +0000
committerCaolan McMahon <caolan@caolanmcmahon.com>2013-01-31 15:12:16 +0000
commit418ae9fb8f03a55255571774a5c0db6faac23120 (patch)
tree21b67b1c0209cec5fe49424a98188d4786429ed6
parente4979da603ddd1568fdbf19df640a041b6f392b4 (diff)
downloadasync-418ae9fb8f03a55255571774a5c0db6faac23120.tar.gz
fix stackoverflows in queue when using synchronous tasks - WARNING, this slightly changes order of events when queue processing using sync tasks
-rw-r--r--lib/async.js27
-rw-r--r--test/test-async.js21
2 files changed, 37 insertions, 11 deletions
diff --git a/lib/async.js b/lib/async.js
index 71903b3..7e8d2d0 100644
--- a/lib/async.js
+++ b/lib/async.js
@@ -706,7 +706,7 @@
data: task,
callback: typeof callback === 'function' ? callback : null
});
- if (q.saturated && q.tasks.length == concurrency) {
+ if (q.saturated && q.tasks.length === concurrency) {
q.saturated();
}
async.nextTick(q.process);
@@ -715,16 +715,33 @@
process: function () {
if (workers < q.concurrency && q.tasks.length) {
var task = q.tasks.shift();
- if(q.empty && q.tasks.length == 0) q.empty();
+ if (q.empty && q.tasks.length === 0) {
+ q.empty();
+ }
workers += 1;
- worker(task.data, only_once(function() {
+ var sync = true;
+ var next = function () {
workers -= 1;
if (task.callback) {
task.callback.apply(task, arguments);
}
- if(q.drain && q.tasks.length + workers == 0) q.drain();
+ if (q.drain && q.tasks.length + workers === 0) {
+ q.drain();
+ }
q.process();
- }));
+ };
+ var cb = only_once(function () {
+ if (sync) {
+ async.nextTick(function () {
+ next.apply(null, arguments);
+ });
+ }
+ else {
+ next.apply(null, arguments);
+ }
+ });
+ worker(task.data, cb);
+ sync = false;
}
},
length: function () {
diff --git a/test/test-async.js b/test/test-async.js
index da6956a..956165d 100644
--- a/test/test-async.js
+++ b/test/test-async.js
@@ -2006,17 +2006,17 @@ exports['queue events'] = function(test) {
test.same(calls, [
'saturated',
'process foo',
- 'foo cb',
'process bar',
- 'bar cb',
'process zoo',
- 'zoo cb',
+ 'foo cb',
'process poo',
- 'poo cb',
+ 'bar cb',
'empty',
'process moo',
+ 'zoo cb',
+ 'poo cb',
'moo cb',
- 'drain',
+ 'drain'
]);
test.done();
};
@@ -2066,7 +2066,16 @@ exports['avoid stack overflows for sync tasks'] = function (test) {
resetCounter,
async.apply(async.doUntil, iter, pred2),
async.apply(async.series, funcarr),
- async.apply(async.parallel, funcarr)
+ async.apply(async.parallel, funcarr),
+ function (callback) {
+ var q = async.queue(function (task, cb) {
+ cb();
+ }, 2);
+ for (var j = 0; j < 10000; j++) {
+ q.push(j);
+ }
+ q.drain = callback;
+ }
],
function (err) {
test.done(err);