-
Notifications
You must be signed in to change notification settings - Fork 30.1k
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
StreamWrap doesn't properly close the wrapped connection #14605
Comments
following |
Is this a bug just in Node 8, or in the previous Node.js versions as well? |
I just ran the script I included earlier using node 7.10.0 and encountered the same problem. |
@tigerbot there is no link to the source code of See #12716 (comment). |
Here is the source of socket-pair: https://git.daplie.com/Daplie/socket-pair/blob/master/lib/socket-pair.js (also fixed the package.json to use an https link rather than a git link) |
@mcollina This is a workaround that's about 4 levels deep. The topmost error that needs to be tested is #8752. However, if that solution happens to work now, it only means that the workaround for this current issue is to use that prior solution... as a workaround - meaning that there is still a bug. @tigerbot Have you tried using |
I recall briefly trying var sockFuncs = [
'address',
'destroy',
'ref',
'unref',
'setEncoding',
'setKeepAlive',
'setNoDelay',
'setTimeout',
];
function wrapConnDuplex(conn, firstChunk) {
var myDuplex = new require('stream').Duplex();
// Handle everything needed for the write part of the Duplex. We need to overwrite the
// `end` function because there is no other way to know when the other side calls it.
myDuplex._write = conn.write.bind(conn);
myDuplex.end = conn.end.bind(conn);
// Handle everything needed for the read part of the Duplex. See the example under
// https://nodejs.org/api/stream.html#stream_readable_push_chunk_encoding.
myDuplex._read = function () {
conn.resume();
};
if (!myDuplex.push(firstChunk)) {
conn.pause();
}
conn.on('data', function (chunk) {
if (!myDuplex.push(chunk)) {
conn.pause();
}
});
conn.on('end', function () {
myDuplex.push(null);
});
// Handle the the things not directly related to reading or writing
conn.on('error', function (err) {
console.error('[error] wrapped socket errored - ' + err.toString());
myDuplex.emit('error', err);
});
conn.on('close', function () {
myDuplex.emit('close');
});
conn.on('timeout', function () {
myDuplex.emit('timeout');
});
sockFuncs.forEach(function (name) {
if (typeof conn[name] !== 'function') {
console.warn('expected `'+name+'` to be a function on wrapped socket');
} else {
myDuplex[name] = conn[name].bind(conn);
}
});
return myDuplex;
} If you use the same code I included above and replace the |
I just tested again with function wrapConnStreamPair(conn, firstChunk) {
var reader = require('stream-pair').create();
var writer = reader.other;
writer.write(firstChunk);
conn.pipe(writer);
writer.pipe(conn);
writer.on('close', conn.destroy.bind(conn));
if (writer.destroy) {
conn.on('close', writer.destroy.bind(writer));
}
return reader;
} |
Also on the note of not trying to wrap it, if you use the following function instead of function noWrap(conn, firstChunk) {
process.nextTick(function () {
conn.unshift(firstChunk);
});
return conn;
} |
This is still an issues in node v9.11.1 |
@addaleax ... should this have been resolved with the refactoring you did here? |
When sockets of the "net" module destroyed, they will call `this._handle.close()` which will also emit EOF if not emitted before. This feature makes sockets on the other side emit "end" and "close" even though we haven't called `end()`. As `stream` of `StreamWrap` are likely to be instances of `net.Socket`, calling `destroy()` manually will avoid issues that don't properly close wrapped connections. Fixes: nodejs#14605
When sockets of the "net" module destroyed, they will call `this._handle.close()` which will also emit EOF if not emitted before. This feature makes sockets on the other side emit "end" and "close" even though we haven't called `end()`. As `stream` of `StreamWrap` are likely to be instances of `net.Socket`, calling `destroy()` manually will avoid issues that don't properly close wrapped connections. Fixes: #14605 PR-URL: #23654 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
When sockets of the "net" module destroyed, they will call `this._handle.close()` which will also emit EOF if not emitted before. This feature makes sockets on the other side emit "end" and "close" even though we haven't called `end()`. As `stream` of `StreamWrap` are likely to be instances of `net.Socket`, calling `destroy()` manually will avoid issues that don't properly close wrapped connections. Fixes: #14605 PR-URL: #23654 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
When sockets of the "net" module destroyed, they will call `this._handle.close()` which will also emit EOF if not emitted before. This feature makes sockets on the other side emit "end" and "close" even though we haven't called `end()`. As `stream` of `StreamWrap` are likely to be instances of `net.Socket`, calling `destroy()` manually will avoid issues that don't properly close wrapped connections. Fixes: #14605 PR-URL: #23654 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
When sockets of the "net" module destroyed, they will call `this._handle.close()` which will also emit EOF if not emitted before. This feature makes sockets on the other side emit "end" and "close" even though we haven't called `end()`. As `stream` of `StreamWrap` are likely to be instances of `net.Socket`, calling `destroy()` manually will avoid issues that don't properly close wrapped connections. Fixes: #14605 PR-URL: #23654 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
When emitting anything other than a fully opened net.Socket object to a TLS server that stream/connection gets wrapped in a way that prevents it from being properly closed when the decrypted side of the connection is destroyed. This makes it difficult to wrap encrypted sockets to get around issue #8752 when I need to peek at the data on the connection before giving it the the TLS server.
You can see that the client connection never receives the close event in the following test case
The text was updated successfully, but these errors were encountered: