Skip to content

Commit d22b2a9

Browse files
committed
timers: do not restart the interval after close
Partially revert 776b73b. Following code crashes after backported timer leak fixes: ```javascript var timer = setInterval(function() { clearInterval(timer); }, 10); timer.unref(); ``` Note that this is actually tested in a `test-timers-unref.js`, and is crashing only with 776b73b. Calling `clearInterval` leads to the crashes in case of `.unref()`ed timers, and might lead to a extra timer spin in case of regular intervals that was closed during the interval callback. All of these happens because `.unref()`ed timer has it's own `_handle` and was used after the `.close()`. PR-URL: #1330 Reviewed-by: Trevor Norris <trev.norris@gmail.com>
1 parent cca5efb commit d22b2a9

2 files changed

Lines changed: 15 additions & 0 deletions

File tree

lib/timers.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,11 @@ exports.setInterval = function(callback, repeat) {
272272

273273
function wrapper() {
274274
timer._repeat.call(this);
275+
276+
// Timer might be closed - no point in restarting it
277+
if (!timer._repeat)
278+
return;
279+
275280
// If timer is unref'd (or was - it's permanently removed from the list.)
276281
if (this._handle) {
277282
this._handle.start(repeat, 0);

src/timer_wrap.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ class TimerWrap : public HandleWrap {
7373
static void Start(const FunctionCallbackInfo<Value>& args) {
7474
TimerWrap* wrap = Unwrap<TimerWrap>(args.Holder());
7575

76+
CHECK(HandleWrap::IsAlive(wrap));
77+
7678
int64_t timeout = args[0]->IntegerValue();
7779
int64_t repeat = args[1]->IntegerValue();
7880
int err = uv_timer_start(&wrap->handle_, OnTimeout, timeout, repeat);
@@ -82,20 +84,26 @@ class TimerWrap : public HandleWrap {
8284
static void Stop(const FunctionCallbackInfo<Value>& args) {
8385
TimerWrap* wrap = Unwrap<TimerWrap>(args.Holder());
8486

87+
CHECK(HandleWrap::IsAlive(wrap));
88+
8589
int err = uv_timer_stop(&wrap->handle_);
8690
args.GetReturnValue().Set(err);
8791
}
8892

8993
static void Again(const FunctionCallbackInfo<Value>& args) {
9094
TimerWrap* wrap = Unwrap<TimerWrap>(args.Holder());
9195

96+
CHECK(HandleWrap::IsAlive(wrap));
97+
9298
int err = uv_timer_again(&wrap->handle_);
9399
args.GetReturnValue().Set(err);
94100
}
95101

96102
static void SetRepeat(const FunctionCallbackInfo<Value>& args) {
97103
TimerWrap* wrap = Unwrap<TimerWrap>(args.Holder());
98104

105+
CHECK(HandleWrap::IsAlive(wrap));
106+
99107
int64_t repeat = args[0]->IntegerValue();
100108
uv_timer_set_repeat(&wrap->handle_, repeat);
101109
args.GetReturnValue().Set(0);
@@ -104,6 +112,8 @@ class TimerWrap : public HandleWrap {
104112
static void GetRepeat(const FunctionCallbackInfo<Value>& args) {
105113
TimerWrap* wrap = Unwrap<TimerWrap>(args.Holder());
106114

115+
CHECK(HandleWrap::IsAlive(wrap));
116+
107117
int64_t repeat = uv_timer_get_repeat(&wrap->handle_);
108118
if (repeat <= 0xfffffff)
109119
args.GetReturnValue().Set(static_cast<uint32_t>(repeat));

0 commit comments

Comments
 (0)