Skip to content

Commit d71ebb9

Browse files
jBarzMylesBorins
authored andcommitted
timer,domain: maintain order of timer callbacks
PR-URL: #10522Fixes: #1271 Reviewed-By: Sam Roberts <vieuxtech@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
1 parent 92f6919 commit d71ebb9

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

‎lib/timers.js‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,19 @@ function TimersList(msecs, unrefed) {
156156
this._timer=newTimerWrap();
157157
this._unrefed=unrefed;
158158
this.msecs=msecs;
159+
this.nextTick=false;
159160
}
160161

161162
functionlistOnTimeout(){
162163
varlist=this._list;
163164
varmsecs=list.msecs;
164165

166+
if(list.nextTick){
167+
list.nextTick=false;
168+
process.nextTick(listOnTimeoutNT,list);
169+
return;
170+
}
171+
165172
debug('timeout callback %d',msecs);
166173

167174
varnow=TimerWrap.now();
@@ -239,6 +246,14 @@ function tryOnTimeout(timer, list) {
239246
}finally{
240247
if(!threw)return;
241248

249+
// Postpone all later list events to next tick. We need to do this
250+
// so that the events are called in the order they were created.
251+
constlists=list._unrefed===true ? unrefedLists : refedLists;
252+
for(varkeyinlists){
253+
if(key>list.msecs){
254+
lists[key].nextTick=true;
255+
}
256+
}
242257
// We need to continue processing after domain error handling
243258
// is complete, but not by using whatever domain was left over
244259
// when the timeout threw its exception.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
constcommon=require('../common');
3+
4+
// This test ensures that the timer callbacks are called in the order in which
5+
// they were created in the event of an unhandled exception in the domain.
6+
7+
constdomain=require('domain').create();
8+
constassert=require('assert');
9+
10+
letfirst=false;
11+
12+
domain.run(function(){
13+
setTimeout(()=>{thrownewError('FAIL');},1);
14+
setTimeout(()=>{first=true;},1);
15+
setTimeout(()=>{assert.strictEqual(first,true);},2);
16+
17+
// Ensure that 2 ms have really passed
18+
leti=1e6;
19+
while(i--);
20+
});
21+
22+
domain.once('error',common.mustCall((err)=>{
23+
assert(err);
24+
assert.strictEqual(err.message,'FAIL');
25+
}));

0 commit comments

Comments
 (0)