Skip to content

Commit 25ec71d

Browse files
theanarkhdanielleadams
authored andcommitted
http: fix http server connection list when close
PR-URL: #43949 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Paolo Insogna <[email protected]> Reviewed-By: Feng Yu <[email protected]>
1 parent 61cd11a commit 25ec71d

File tree

3 files changed

+58
-5
lines changed

3 files changed

+58
-5
lines changed

lib/_http_common.js

+1
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ function freeParser(parser, req, socket) {
182182
if (parser._consumed)
183183
parser.unconsume();
184184
cleanParser(parser);
185+
parser.remove();
185186
if (parsers.free(parser) === false) {
186187
// Make sure the parser's stack has unwound before deleting the
187188
// corresponding C++ object through .close().

src/node_http_parser.cc

+10-5
Original file line numberDiff line numberDiff line change
@@ -548,17 +548,21 @@ class Parser : public AsyncWrap, public StreamListener {
548548
Parser* parser;
549549
ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
550550

551-
if (parser->connectionsList_ != nullptr) {
552-
parser->connectionsList_->Pop(parser);
553-
parser->connectionsList_->PopActive(parser);
554-
}
555-
556551
// Since the Parser destructor isn't going to run the destroy() callbacks
557552
// it needs to be triggered manually.
558553
parser->EmitTraceEventDestroy();
559554
parser->EmitDestroy();
560555
}
561556

557+
static void Remove(const FunctionCallbackInfo<Value>& args) {
558+
Parser* parser;
559+
ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
560+
561+
if (parser->connectionsList_ != nullptr) {
562+
parser->connectionsList_->Pop(parser);
563+
parser->connectionsList_->PopActive(parser);
564+
}
565+
}
562566

563567
void Save() {
564568
url_.Save();
@@ -1221,6 +1225,7 @@ void InitializeHttpParser(Local<Object> target,
12211225
t->Inherit(AsyncWrap::GetConstructorTemplate(env));
12221226
env->SetProtoMethod(t, "close", Parser::Close);
12231227
env->SetProtoMethod(t, "free", Parser::Free);
1228+
env->SetProtoMethod(t, "remove", Parser::Remove);
12241229
env->SetProtoMethod(t, "execute", Parser::Execute);
12251230
env->SetProtoMethod(t, "finish", Parser::Finish);
12261231
env->SetProtoMethod(t, "initialize", Parser::Initialize);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const http = require('http');
5+
6+
function request(server) {
7+
http.get({
8+
port: server.address().port,
9+
path: '/',
10+
}, (res) => {
11+
res.resume();
12+
});
13+
}
14+
15+
{
16+
const server = http.createServer((req, res) => {
17+
// Hack to not remove parser out of server.connectionList
18+
// See `freeParser` in _http_common.js
19+
req.socket.parser.free = common.mustCall();
20+
req.socket.on('close', common.mustCall(() => {
21+
server.close();
22+
}));
23+
res.end('ok');
24+
}).listen(0, common.mustCall(() => {
25+
request(server);
26+
}));
27+
}
28+
29+
{
30+
const server = http.createServer((req, res) => {
31+
// See `freeParser` in _http_common.js
32+
const { parser } = req.socket;
33+
parser.free = common.mustCall(() => {
34+
setImmediate(common.mustCall(() => {
35+
parser.close();
36+
}));
37+
});
38+
req.socket.on('close', common.mustCall(() => {
39+
setImmediate(common.mustCall(() => {
40+
server.close();
41+
}));
42+
}));
43+
res.end('ok');
44+
}).listen(0, common.mustCall(() => {
45+
request(server);
46+
}));
47+
}

0 commit comments

Comments
 (0)