Skip to content

Commit 9f79341

Browse files
mcollinaBethGriggs
authored andcommitted
http2: check if stream is not destroyed before sending trailers
Fixes: #22855 Backport-PR-URL: #22850 PR-URL: #22896 Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 2de17ea commit 9f79341

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

lib/internal/http2/core.js

+8
Original file line numberDiff line numberDiff line change
@@ -1475,6 +1475,14 @@ function afterShutdown() {
14751475
}
14761476

14771477
function finishSendTrailers(stream, headersList) {
1478+
// The stream might be destroyed and in that case
1479+
// there is nothing to do.
1480+
// This can happen because finishSendTrailers is
1481+
// scheduled via setImmediate.
1482+
if (stream.destroyed) {
1483+
return;
1484+
}
1485+
14781486
stream[kState].flags &= ~STREAM_FLAGS_HAS_TRAILERS;
14791487

14801488
const ret = stream[kHandle].trailers(headersList);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const { mustCall } = common;
5+
6+
if (!common.hasCrypto)
7+
common.skip('missing crypto');
8+
9+
const http2 = require('http2');
10+
const assert = require('assert');
11+
12+
const {
13+
HTTP2_HEADER_PATH,
14+
HTTP2_HEADER_METHOD,
15+
} = http2.constants;
16+
17+
// This tests verifies that calling `req.socket.destroy()` via
18+
// setImmediate does not crash.
19+
// Fixes https://github.com/nodejs/node/issues/22855.
20+
21+
const app = http2.createServer(mustCall((req, res) => {
22+
res.end('hello');
23+
setImmediate(() => req.socket.destroy());
24+
}));
25+
26+
app.listen(0, mustCall(() => {
27+
const session = http2.connect(`http://localhost:${app.address().port}`);
28+
const request = session.request({
29+
[HTTP2_HEADER_PATH]: '/',
30+
[HTTP2_HEADER_METHOD]: 'get'
31+
});
32+
request.once('response', mustCall((headers, flags) => {
33+
let data = '';
34+
request.on('data', (chunk) => { data += chunk; });
35+
request.on('end', mustCall(() => {
36+
assert.strictEqual(data, 'hello');
37+
session.close();
38+
app.close();
39+
}));
40+
}));
41+
request.end();
42+
}));

0 commit comments

Comments
 (0)