-
-
Notifications
You must be signed in to change notification settings - Fork 33.5k
Open
Labels
http2Issues or PRs related to the http2 subsystem.Issues or PRs related to the http2 subsystem.streamIssues and PRs related to the stream subsystem.Issues and PRs related to the stream subsystem.
Description
The following conditions cause an error event on http2stream
, even though http2stream
received all data and RST_STREAM from a client.
http2stream
is not destroyed(does not consume all data)- goaway frame is not received
- socket error happens
http2stream
received all data and RST_STREAM
Socket error without goaway frame causes a http2session.destroy(err)
.
node/lib/internal/http2/core.js
Lines 2678 to 2688 in 81bc7b3
function socketOnError(error) { | |
const session = this[kSession]; | |
if (session !== undefined) { | |
// We can ignore ECONNRESET after GOAWAY was received as there's nothing | |
// we can do and the other side is fully within its rights to do so. | |
if (error.code === 'ECONNRESET' && session[kState].goawayCode !== null) | |
return session.destroy(); | |
debugSessionObj(this, 'socket error [%s]', error.message); | |
session.destroy(error); | |
} | |
} |
http2session.destroy(err)
propagate error to http2stream.destroy(err)
.
node/lib/internal/http2/core.js
Lines 1298 to 1323 in 81bc7b3
destroy(error = NGHTTP2_NO_ERROR, code) { | |
if (this.destroyed) | |
return; | |
debugSessionObj(this, 'destroying'); | |
if (typeof error === 'number') { | |
code = error; | |
error = | |
code !== NGHTTP2_NO_ERROR ? | |
new ERR_HTTP2_SESSION_ERROR(code) : undefined; | |
} | |
if (code === undefined && error != null) | |
code = NGHTTP2_INTERNAL_ERROR; | |
const state = this[kState]; | |
state.flags |= SESSION_FLAGS_DESTROYED; | |
state.destroyCode = code; | |
// Clear timeout and remove timeout listeners | |
this.setTimeout(0); | |
this.removeAllListeners('timeout'); | |
// Destroy any pending and open streams | |
const cancel = new ERR_HTTP2_STREAM_CANCEL(error); | |
state.pendingStreams.forEach((stream) => stream.destroy(cancel)); | |
state.streams.forEach((stream) => stream.destroy(error)); |
I thought that http2stream
got RST_STREAM means that there is no error about processing data. So, I thought if http2stream
is closed by RST_STREAM, connection error should not cause http2stream
error.
The codes to reproduce.
'use strict';
const common = require('../common');
const fixtures = require('../common/fixtures');
const http2 = require('http2');
const fs = require('fs');
const net = require('net');
const tmpdir = require('../common/tmpdir');
tmpdir.refresh();
const loc = fixtures.path('person-large.jpg');
const server = http2.createServer();
let session_;
server.on('session', (session)=>{
session_ = session;
});
server.on('stream', common.mustCall((stream) => {
let sum = 0;
stream.pause();
const slowRead = ()=>{
setTimeout(()=>{
const data = stream.read(stream._readableState.highWaterMark/10);
sum += data ? data.length: 0;
console.log('read:' + sum + ' soc:' + socket.bytesWritten + ' closed:' + stream.closed + ' destroyed:' + stream.destroyed);
if(stream.closed){ // Got RST_STREAM and stream was closed but all data isn't processed.
socket.destroy(); // destroy connection without goaway frame.
try{
session_.ping(()=>{}); // activate read.
}catch(err){
console.log(err);
}
}
slowRead();
}, 10)
};
slowRead();
stream.respond();
stream.end();
stream.on('error', (err)=>{
// Stream allready closed, but error event happens.
console.log(err);
});
}));
let socket;
server.listen(0, common.mustCall(() => {
const options = {
createConnection: (authority, options) => {
socket = net.connect(server.address().port, 'localhost');
return socket;
}
}
const client = http2.connect(`http://localhost:${server.address().port}`, options);
const req = client.request({ ':method': 'POST' });
req.on('response', common.mustCall());
req.resume();
const str = fs.createReadStream(loc);
str.on('end', common.mustCall());
str.pipe(req);
}));
Metadata
Metadata
Assignees
Labels
http2Issues or PRs related to the http2 subsystem.Issues or PRs related to the http2 subsystem.streamIssues and PRs related to the stream subsystem.Issues and PRs related to the stream subsystem.