Skip to content

Commit 5e32d5f

Browse files
ronagBridgeAR
authored andcommitted
stream: don't deadlock on aborted stream
Not all streams (e.g. http.ClientRequest) will always emit 'close' after 'aborted'. PR-URL: #29376 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Luigi Pinca <[email protected]>
1 parent 78aa937 commit 5e32d5f

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

lib/internal/streams/end-of-stream.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,18 @@ function eos(stream, opts, callback) {
8282
stream.on('close', onlegacyfinish);
8383
}
8484

85+
// Not all streams will emit 'close' after 'aborted'.
86+
if (typeof stream.aborted === 'boolean') {
87+
stream.on('aborted', onclose);
88+
}
89+
8590
stream.on('end', onend);
8691
stream.on('finish', onfinish);
8792
if (opts.error !== false) stream.on('error', onerror);
8893
stream.on('close', onclose);
8994

9095
return function() {
96+
stream.removeListener('aborted', onclose);
9197
stream.removeListener('complete', onfinish);
9298
stream.removeListener('abort', onclose);
9399
stream.removeListener('request', onrequest);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'use strict';
2+
const common = require('../common');
3+
const http = require('http');
4+
const { finished } = require('stream');
5+
6+
{
7+
// Test abort before finished.
8+
9+
const server = http.createServer(function(req, res) {
10+
res.write('asd');
11+
});
12+
13+
server.listen(0, common.mustCall(function() {
14+
http.request({
15+
port: this.address().port
16+
})
17+
.on('response', (res) => {
18+
res.on('readable', () => {
19+
res.destroy();
20+
});
21+
finished(res, common.mustCall(() => {
22+
server.close();
23+
}));
24+
})
25+
.end();
26+
}));
27+
}

0 commit comments

Comments
 (0)