Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/timers.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ function listOnTimeout() {
if (domain)
domain.enter();
threw = true;
first._called = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add this._called = false to the constructor.

first._onTimeout();
if (domain)
domain.exit();
Expand Down Expand Up @@ -305,6 +306,9 @@ Timeout.prototype.unref = function() {
if (this._handle) {
this._handle.unref();
} else if (typeof(this._onTimeout) === 'function') {
// Prevent running callback multiple times
// when unref() is called during the callback
if (this._called) return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's probably best to just do this before if (this._handle) {, but I'm not 100% sure it matters.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I was unsure here too, but since I only wanted to prevent the _onTimeout call, this seemed right.

var now = Timer.now();
if (!this._idleStart) this._idleStart = now;
var delay = this._idleStart + this._idleTimeout - now;
Expand Down Expand Up @@ -492,6 +496,7 @@ function unrefTimeout() {
if (domain) domain.enter();
threw = true;
debug('unreftimer firing timeout');
first._called = true;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strictly, this one wasn't neccessary to fix the issue, but I thought it's better to track all callback calls if there are more edge cases.

first._onTimeout();
threw = false;
if (domain)
Expand Down
7 changes: 7 additions & 0 deletions test/parallel/test-timers-unref.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var interval_fired = false,
timeout_fired = false,
unref_interval = false,
unref_timer = false,
unref_callbacks = 0,
interval, check_unref, checks = 0;

var LONG_TIME = 10 * 1000;
Expand Down Expand Up @@ -34,6 +35,11 @@ check_unref = setInterval(function() {
checks += 1;
}, 100);

setTimeout(function() {
unref_callbacks++;
this.unref();
}, SHORT_TIME);

// Should not assert on args.Holder()->InternalFieldCount() > 0. See #4261.
(function() {
var t = setInterval(function() {}, 1);
Expand All @@ -46,4 +52,5 @@ process.on('exit', function() {
assert.strictEqual(timeout_fired, false, 'Timeout should not fire');
assert.strictEqual(unref_timer, true, 'An unrefd timeout should still fire');
assert.strictEqual(unref_interval, true, 'An unrefd interval should still fire');
assert.strictEqual(unref_callbacks, 1, 'Callback should only run once');
});