Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 951168f

Browse files
committedMar 21, 2015
timers: assure setTimeout callback only runs once
This fixes an edge case where running this.unref() during the callback caused the callback to get executed multiple times.
1 parent 99c79f8 commit 951168f

File tree

2 files changed

+12
-0
lines changed

2 files changed

+12
-0
lines changed
 

‎lib/timers.js

+5
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ function listOnTimeout() {
8585
if (domain)
8686
domain.enter();
8787
threw = true;
88+
first._called = true;
8889
first._onTimeout();
8990
if (domain)
9091
domain.exit();
@@ -305,6 +306,9 @@ Timeout.prototype.unref = function() {
305306
if (this._handle) {
306307
this._handle.unref();
307308
} else if (typeof(this._onTimeout) === 'function') {
309+
// Prevent running callback multiple times
310+
// when unref() is called during the callback
311+
if (this._called) return;
308312
var now = Timer.now();
309313
if (!this._idleStart) this._idleStart = now;
310314
var delay = this._idleStart + this._idleTimeout - now;
@@ -492,6 +496,7 @@ function unrefTimeout() {
492496
if (domain) domain.enter();
493497
threw = true;
494498
debug('unreftimer firing timeout');
499+
first._called = true;
495500
first._onTimeout();
496501
threw = false;
497502
if (domain)

‎test/parallel/test-timers-unref.js

+7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ var interval_fired = false,
55
timeout_fired = false,
66
unref_interval = false,
77
unref_timer = false,
8+
unref_callbacks = 0,
89
interval, check_unref, checks = 0;
910

1011
var LONG_TIME = 10 * 1000;
@@ -34,6 +35,11 @@ check_unref = setInterval(function() {
3435
checks += 1;
3536
}, 100);
3637

38+
setTimeout(function() {
39+
unref_callbacks++;
40+
this.unref();
41+
}, SHORT_TIME);
42+
3743
// Should not assert on args.Holder()->InternalFieldCount() > 0. See #4261.
3844
(function() {
3945
var t = setInterval(function() {}, 1);
@@ -46,4 +52,5 @@ process.on('exit', function() {
4652
assert.strictEqual(timeout_fired, false, 'Timeout should not fire');
4753
assert.strictEqual(unref_timer, true, 'An unrefd timeout should still fire');
4854
assert.strictEqual(unref_interval, true, 'An unrefd interval should still fire');
55+
assert.strictEqual(unref_callbacks, 1, 'Callback should only run once');
4956
});

0 commit comments

Comments
 (0)
Please sign in to comment.