net: make Socket destroy() re-entrance safe

So that we are free to call socket.destroy() in error event handler.

fix #6769
This commit is contained in:
Jun Ma 2014-01-26 01:50:17 +08:00 коммит произвёл Fedor Indutny
Родитель b4c4e0bbaa
Коммит d2de8ba34d
2 изменённых файлов: 37 добавлений и 1 удалений

Просмотреть файл

@ -469,8 +469,11 @@ Socket.prototype._destroy = function(exception, cb) {
this._handle = null;
}
fireErrorCallbacks();
// we set destroyed to true before firing error callbacks in order
// to make it re-entrance safe in case Socket.prototype.destroy()
// is called within callbacks
this.destroyed = true;
fireErrorCallbacks();
if (this.server) {
COUNTER_NET_SERVER_CONNECTION_CLOSE(this);

Просмотреть файл

@ -37,3 +37,36 @@ s.destroy();
assert.equal(9, s.server.connections);
s.destroy();
assert.equal(9, s.server.connections);
var SIZE = 2E6;
var N = 10;
var buf = new Buffer(SIZE);
buf.fill(0x61); // 'a'
var server = net.createServer(function(socket) {
socket.setNoDelay();
socket.on('error', function(err) {
socket.destroy();
}).on('close', function() {
server.close();
})
for (var i = 0; i < N; ++i) {
socket.write(buf, function() { });
}
socket.end();
}).listen(common.PORT, function() {
var conn = net.connect(common.PORT);
conn.on('data', function(buf) {
conn.pause();
setTimeout(function() {
conn.destroy();
}, 20);
});
});
process.on('exit', function() {
assert.equal(server.connections, 0);
});