Skip to content

Commit ec2037d

Browse files
santigimenoMylesBorins
authored andcommitted
child_process: fix leak when passing http sockets
After passing an HTTP socket, release its associated resources. PR-URL: #20305Fixes: #15651 Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 57e5a3e commit ec2037d

2 files changed

Lines changed: 66 additions & 0 deletions

File tree

‎lib/internal/child_process.js‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ const SocketList = require('internal/socket_list');
3131
const{ convertToValidSignal }=require('internal/util');
3232
const{ isUint8Array }=require('internal/util/types');
3333
constspawn_sync=process.binding('spawn_sync');
34+
const{ HTTPParser }=process.binding('http_parser');
35+
const{ freeParser }=require('_http_common');
3436

3537
const{
3638
UV_EACCES,
@@ -107,6 +109,14 @@ const handleConversion = {
107109
if(!options.keepOpen){
108110
handle.onread=nop;
109111
socket._handle=null;
112+
socket.setTimeout(0);
113+
// In case of an HTTP connection socket, release the associated
114+
// resources
115+
if(socket.parser&&socket.parserinstanceofHTTPParser){
116+
freeParser(socket.parser,null,socket);
117+
if(socket._httpMessage)
118+
socket._httpMessage.detachSocket(socket);
119+
}
110120
}
111121

112122
returnhandle;
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Flags: --expose_internals
2+
3+
'use strict';
4+
5+
constcommon=require('../common');
6+
constassert=require('assert');
7+
const{ fork }=require('child_process');
8+
consthttp=require('http');
9+
const{ kTimeout }=require('internal/timers');
10+
11+
if(process.argv[2]==='child'){
12+
process.once('message',(req,socket)=>{
13+
constres=newhttp.ServerResponse(req);
14+
res.assignSocket(socket);
15+
res.end();
16+
});
17+
18+
process.send('ready');
19+
return;
20+
}
21+
22+
letchild;
23+
letsocket;
24+
25+
constserver=http.createServer(common.mustCall((req,res)=>{
26+
constr={
27+
method: req.method,
28+
headers: req.headers,
29+
path: req.path,
30+
httpVersionMajor: req.httpVersionMajor,
31+
query: req.query,
32+
};
33+
34+
socket=res.socket;
35+
child.send(r,socket);
36+
server.close();
37+
}));
38+
39+
server.listen(0,common.mustCall(()=>{
40+
child=fork(__filename,['child']);
41+
child.once('message',(msg)=>{
42+
assert.strictEqual(msg,'ready');
43+
constreq=http.request({
44+
port: server.address().port,
45+
},common.mustCall((res)=>{
46+
res.on('data',()=>{});
47+
res.on('end',common.mustCall(()=>{
48+
assert.strictEqual(socket[kTimeout]._idleTimeout,-1);
49+
assert.strictEqual(socket.parser,null);
50+
assert.strictEqual(socket._httpMessage,null);
51+
}));
52+
}));
53+
54+
req.end();
55+
});
56+
}));

0 commit comments

Comments
 (0)