-
Notifications
You must be signed in to change notification settings - Fork 29.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Http2: Cannot read property 'finishWrite' of null #35695
Comments
This is a collection of various minor issues all linked to the edge case of the underlying stream of the TLS listener being null after being indirectly removed by the |
The segfault does not occur with the new crypto_tls code, it occurs only on v14.x |
@mmomtchev |
I was able to compress it down to this unit test: 'use strict';
const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');
const h2 = require('http2');
const net = require('net');
const fixtures = require('../common/fixtures');
const { Duplex } = require('stream');
const server = h2.createSecureServer({
key: fixtures.readKey('agent1-key.pem'),
cert: fixtures.readKey('agent1-cert.pem')
});
class JSSocket extends Duplex {
constructor(socket) {
super();
socket.on('close', () => this.destroy());
socket.on('data', (data) => this.push(data));
this.socket = socket;
}
_write(data, encoding, callback) {
this.socket.write(data, encoding, callback);
}
_read(size) {
}
}
server.listen(0, common.mustCall(function() {
const socket = net.connect({
host: 'localhost',
port: this.address().port
}, () => {
const client = h2.connect(`https://localhost:${this.address().port}`, {
rejectUnauthorized: false,
socket: new JSSocket(socket)
});
const req = client.request();
setTimeout(() => socket.destroy(), 500);
setTimeout(() => client.close(), 1000);
setTimeout(() => server.close(), 1500);
req.on('close', common.mustCall(() => { }));
});
})); With JSSocket - exception on Node 14.x and master |
The reason I try to spawn the server in a new process and kill the server is I want server send RST packet(not FIN packet) to end the connection. Maybe the error RST end the connection is not the same as FIN. |
@jasnell, @addaleax is |
using createConnection instead: ...
const client = h2.connect(`https://localhost:${this.address().port}`, {
rejectUnauthorized: false,
createConnection: () => tls.connect({
socket: new JSSocket(socket),
host: 'localhost', port: this.address().port, ALPNProtocols: ['h2']
}),
// socket: new JSSocket(socket)
});
... the same error:
but this can prevent the error: ...
createConnection: () => {
const jsSocket = new JSSocket(socket)
const tlsSocket = tls.connect({
socket: jsSocket,
host: 'localhost', port: this.address().port, ALPNProtocols: ['h2']
})
// tlsSocket.on('close', ()=>{jsSocket.destroy()})
jsSocket.on('close', ()=>{tlsSocket.destroy()}) // <-- add this line
return tlsSocket
}
... |
@panmenghan the exception is trivial to fix on the |
@mmomtchev Thanks, please fix it. I already rewrite my code to use |
@panmenghan the bug is in the http2 code |
Move the socket event binding to the HTTP2Session constructor so that an error event could be delivered should the constructor fail Ref: nodejs#35772 PR-URL: nodejs#35772 Fixes: nodejs#35695 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ricky Zhou <0x19951125@gmail.com>
When using a JSStreamSocket, the HTTP2Session constructor will replace the socket object http2 events should be attached to the JSStreamSocket object because the http2 session handle lives there Fixes: #35695 PR-URL: #35772 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ricky Zhou <0x19951125@gmail.com>
Move the socket event binding to the HTTP2Session constructor so that an error event could be delivered should the constructor fail Ref: #35772 PR-URL: #35772 Fixes: #35695 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ricky Zhou <0x19951125@gmail.com>
When using a JSStreamSocket, the HTTP2Session constructor will replace the socket object http2 events should be attached to the JSStreamSocket object because the http2 session handle lives there Fixes: #35695 PR-URL: #35772 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ricky Zhou <0x19951125@gmail.com>
Move the socket event binding to the HTTP2Session constructor so that an error event could be delivered should the constructor fail Ref: #35772 PR-URL: #35772 Fixes: #35695 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ricky Zhou <0x19951125@gmail.com>
When using a JSStreamSocket, the HTTP2Session constructor will replace the socket object http2 events should be attached to the JSStreamSocket object because the http2 session handle lives there Fixes: #35695 PR-URL: #35772 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ricky Zhou <0x19951125@gmail.com>
Move the socket event binding to the HTTP2Session constructor so that an error event could be delivered should the constructor fail Ref: #35772 PR-URL: #35772 Fixes: #35695 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ricky Zhou <0x19951125@gmail.com>
When using a JSStreamSocket, the HTTP2Session constructor will replace the socket object http2 events should be attached to the JSStreamSocket object because the http2 session handle lives there Fixes: #35695 PR-URL: #35772 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ricky Zhou <0x19951125@gmail.com>
Move the socket event binding to the HTTP2Session constructor so that an error event could be delivered should the constructor fail Ref: #35772 PR-URL: #35772 Fixes: #35695 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ricky Zhou <0x19951125@gmail.com>
The example from first comment is reproducible in NodeJS 14.16.1. |
This PR reworks the last couple days' worth of effort to do something useful when connected sockets time out. Notably, during the course of this work, I ran into another case of the `null...finishWrite` exception. Existing Node bugs (the latter was filed by me): * <nodejs/node#35695> * <nodejs/node#46094>
v14.14.0 + v12.19.0
Win10(2004, 64bit) + Ubuntu 18.04.4(wsl2, Linux 4.19.128-microsoft-standard SMP Tue Jun 23 12:58:10 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux)
http2
What steps will reproduce the bug?
server.js
client.js
the error(bug):
client.js argv(command line options) mean:
Win10(2004)
Ubuntu 18.04.4(wsl2)
How often does it reproduce? Is there a required condition?
What is the expected behavior?
No "TypeError: Cannot read property 'finishShutdown' of null" error
What do you see instead?
Additional information
The text was updated successfully, but these errors were encountered: