Skip to content

Commit 16f2600

Browse files
cjihrigaddaleax
authored andcommitted
child_process: emit IPC messages on next tick
This commit fixes a regression related to IPC 'message' events. When messages are not emitted in the next tick, a 'message' handler that throws can break the IPC read loop. Refs: #6909 Refs: #13459 Refs: #13648 PR-URL: #13856 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Santiago Gimeno <[email protected]>
1 parent f2d7b80 commit 16f2600

File tree

2 files changed

+46
-11
lines changed

2 files changed

+46
-11
lines changed

‎lib/internal/child_process.js‎

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,6 @@ function setupChannel(target, channel){
456456
}
457457
chunks[0]=jsonBuffer+chunks[0];
458458

459-
varnextTick=false;
460459
for(vari=0;i<numCompleteChunks;i++){
461460
varmessage=JSON.parse(chunks[i]);
462461

@@ -465,12 +464,11 @@ function setupChannel(target, channel){
465464
// that we deliver the handle with the right message however.
466465
if(isInternal(message)){
467466
if(message.cmd==='NODE_HANDLE')
468-
handleMessage(message,recvHandle,true,false);
467+
handleMessage(message,recvHandle,true);
469468
else
470-
handleMessage(message,undefined,true,false);
469+
handleMessage(message,undefined,true);
471470
}else{
472-
handleMessage(message,undefined,false,nextTick);
473-
nextTick=true;
471+
handleMessage(message,undefined,false);
474472
}
475473
}
476474
jsonBuffer=incompleteChunk;
@@ -532,7 +530,7 @@ function setupChannel(target, channel){
532530

533531
// Convert handle object
534532
obj.got.call(this,message,handle,function(handle){
535-
handleMessage(message.msg,handle,isInternal(message.msg),false);
533+
handleMessage(message.msg,handle,isInternal(message.msg));
536534
});
537535
});
538536

@@ -742,15 +740,13 @@ function setupChannel(target, channel){
742740
target.emit(event,message,handle);
743741
}
744742

745-
functionhandleMessage(message,handle,internal,nextTick){
743+
functionhandleMessage(message,handle,internal){
746744
if(!target.channel)
747745
return;
748746

749747
vareventName=(internal ? 'internalMessage' : 'message');
750-
if(nextTick)
751-
process.nextTick(emit,eventName,message,handle);
752-
else
753-
target.emit(eventName,message,handle);
748+
749+
process.nextTick(emit,eventName,message,handle);
754750
}
755751

756752
channel.readStart();
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
'use strict';
2+
constcommon=require('../common');
3+
constassert=require('assert');
4+
constcp=require('child_process');
5+
constNUM_MESSAGES=10;
6+
constvalues=[];
7+
8+
for(leti=0;i<NUM_MESSAGES;++i){
9+
values[i]=i;
10+
}
11+
12+
if(process.argv[2]==='child'){
13+
constreceived=values.map(()=>{returnfalse;});
14+
15+
process.on('uncaughtException',common.mustCall((err)=>{
16+
received[err]=true;
17+
constdone=received.every((element)=>{returnelement===true;});
18+
19+
if(done)
20+
process.disconnect();
21+
},NUM_MESSAGES));
22+
23+
process.on('message',(msg)=>{
24+
// If messages are handled synchronously, throwing should break the IPC
25+
// message processing.
26+
throwmsg;
27+
});
28+
29+
process.send('ready');
30+
}else{
31+
constchild=cp.fork(__filename,['child']);
32+
33+
child.on('message',common.mustCall((msg)=>{
34+
assert.strictEqual(msg,'ready');
35+
values.forEach((value)=>{
36+
child.send(value);
37+
});
38+
}));
39+
}

0 commit comments

Comments
(0)