diff --git a/lib/net.js b/lib/net.js index e624adfcc3e..31de90cb024 100644 --- a/lib/net.js +++ b/lib/net.js @@ -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); diff --git a/test/simple/test-net-stream.js b/test/simple/test-net-stream.js index 429995ab93f..9f2db51be82 100644 --- a/test/simple/test-net-stream.js +++ b/test/simple/test-net-stream.js @@ -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); +});