| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 6885dcc commit 632aee1
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -222,7 +222,6 @@ function listOnTimeout() { | |||
| 222 | 222 | // As such, we can remove the list and clean up the TimerWrap C++ handle. | |
| 223 | 223 | debug('%d list empty', msecs); | |
| 224 | 224 | assert(L.isEmpty(list)); | |
| 225 | - this.close(); | ||
| 226 | 225 | ||
| 227 | 226 | // Either refedLists[msecs] or unrefedLists[msecs] may have been removed and | |
| 228 | 227 | // recreated since the reference to `list` was created. Make sure they're | |
@@ -232,6 +231,13 @@ function listOnTimeout() { | |||
| 232 | 231 | } else if (list === refedLists[msecs]) { | |
| 233 | 232 | delete refedLists[msecs]; | |
| 234 | 233 | } | |
| 234 | + | ||
| 235 | + // Do not close the underlying handle if its ownership has changed | ||
| 236 | + // (e.g it was unrefed in its callback). | ||
| 237 | + if (this.owner) | ||
| 238 | + return; | ||
| 239 | + | ||
| 240 | + this.close(); | ||
| 235 | 241 | } | |
| 236 | 242 | ||
| 237 | 243 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,61 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + // Checks that setInterval timers keep running even when they're | ||
| 3 | + // unrefed within their callback. | ||
| 4 | + | ||
| 5 | + require('../common'); | ||
| 6 | + const assert = require('assert'); | ||
| 7 | + const net = require('net'); | ||
| 8 | + | ||
| 9 | + let counter1 = 0; | ||
| 10 | + let counter2 = 0; | ||
| 11 | + | ||
| 12 | + // Test1 checks that clearInterval works as expected for a timer | ||
| 13 | + // unrefed within its callback: it removes the timer and its callback | ||
| 14 | + // is not called anymore. Note that the only reason why this test is | ||
| 15 | + // robust is that: | ||
| 16 | + // 1. the repeated timer it creates has a delay of 1ms | ||
| 17 | + // 2. when this test is completed, another test starts that creates a | ||
| 18 | + // new repeated timer with the same delay (1ms) | ||
| 19 | + // 3. because of the way timers are implemented in libuv, if two | ||
| 20 | + // repeated timers A and B are created in that order with the same | ||
| 21 | + // delay, it is guaranteed that the first occurrence of timer A | ||
| 22 | + // will fire before the first occurrence of timer B | ||
| 23 | + // 4. as a result, when the timer created by Test2 fired 11 times, if | ||
| 24 | + // the timer created by Test1 hadn't been removed by clearInterval, | ||
| 25 | + // it would have fired 11 more times, and the assertion in the | ||
| 26 | + // process'exit event handler would fail. | ||
| 27 | + function Test1() { | ||
| 28 | + // server only for maintaining event loop | ||
| 29 | + const server = net.createServer().listen(0); | ||
| 30 | + | ||
| 31 | + const timer1 = setInterval(() => { | ||
| 32 | + timer1.unref(); | ||
| 33 | + if (counter1++ === 3) { | ||
| 34 | + clearInterval(timer1); | ||
| 35 | + server.close(() => { | ||
| 36 | + Test2(); | ||
| 37 | + }); | ||
| 38 | + } | ||
| 39 | + }, 1); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + | ||
| 43 | + // Test2 checks setInterval continues even if it is unrefed within | ||
| 44 | + // timer callback. counter2 continues to be incremented more than 11 | ||
| 45 | + // until server close completed. | ||
| 46 | + function Test2() { | ||
| 47 | + // server only for maintaining event loop | ||
| 48 | + const server = net.createServer().listen(0); | ||
| 49 | + | ||
| 50 | + const timer2 = setInterval(() => { | ||
| 51 | + timer2.unref(); | ||
| 52 | + if (counter2++ === 3) | ||
| 53 | + server.close(); | ||
| 54 | + }, 1); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + process.on('exit', () => { | ||
| 58 | + assert.strictEqual(counter1, 4); | ||
| 59 | + }); | ||
| 60 | + | ||
| 61 | + Test1(); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments