http: fix resource leak

Fixes #2069
This commit is contained in:
koichik 2011-11-29 20:55:05 +09:00
parent 0de6ec5f08
commit 7aa5924dc6
4 changed files with 41 additions and 21 deletions

View File

@ -896,6 +896,10 @@ function Agent(options) {
var name = host + ':' + port;
if (self.requests[name] && self.requests[name].length) {
self.requests[name].shift().onSocket(socket);
if (self.requests[name].length === 0) {
// don't leak
delete this.requests[name];
}
} else {
// If there are no pending requests just destroy the
// socket and it will get removed from the pool. This
@ -963,11 +967,11 @@ Agent.prototype.removeSocket = function(s, name, host, port) {
var index = this.sockets[name].indexOf(s);
if (index !== -1) {
this.sockets[name].splice(index, 1);
if (this.sockets[name].length === 0) {
// don't leak
delete this.sockets[name];
}
}
} else if (this.sockets[name] && this.sockets[name].length === 0) {
// don't leak
delete this.sockets[name];
delete this.requests[name];
}
if (this.requests[name] && this.requests[name].length) {
// If we have pending requests and a socket gets closed a new one

View File

@ -52,9 +52,12 @@ function request(i) {
var socket = req.socket;
socket.on('close', function() {
++count;
assert.equal(http.globalAgent.sockets[name].length, max - count);
assert.equal(http.globalAgent.sockets[name].indexOf(socket), -1);
if (count === max) {
if (count < max) {
assert.equal(http.globalAgent.sockets[name].length, max - count);
assert.equal(http.globalAgent.sockets[name].indexOf(socket), -1);
} else {
assert(!http.globalAgent.sockets.hasOwnProperty(name));
assert(!http.globalAgent.requests.hasOwnProperty(name));
server.close();
}
});

View File

@ -22,10 +22,8 @@
var common = require('../common');
var assert = require('assert');
var http = require('http');
var util = require('util');
var body = 'hello world\n';
var headers = {'connection': 'keep-alive'};
var server = http.createServer(function(req, res) {
res.writeHead(200, {'Content-Length': body.length});
@ -34,23 +32,37 @@ var server = http.createServer(function(req, res) {
});
var connectCount = 0;
var name = 'localhost:' + common.PORT;
var agent = new http.Agent({maxSockets: 1});
var headers = {'connection': 'keep-alive'};
server.listen(common.PORT, function() {
var agent = new http.Agent({maxSockets: 1});
var request = http.request({method: 'GET', path: '/', headers: headers, port: common.PORT, agent: agent}, function() {
assert.equal(1, agent.sockets['localhost:' + common.PORT].length);
http.get({
path: '/', headers: headers, port: common.PORT, agent: agent
}, function(response) {
assert.equal(agent.sockets[name].length, 1);
assert.equal(agent.requests[name].length, 2);
});
request.end();
request = http.request({method: 'GET', path: '/', headers: headers, port: common.PORT, agent: agent}, function() {
assert.equal(1, agent.sockets['localhost:' + common.PORT].length);
http.get({
path: '/', headers: headers, port: common.PORT, agent: agent
}, function(response) {
assert.equal(agent.sockets[name].length, 1);
assert.equal(agent.requests[name].length, 1);
});
request.end();
request = http.request({method: 'GET', path: '/', headers: headers, port: common.PORT, agent: agent}, function(response) {
http.get({
path: '/', headers: headers, port: common.PORT, agent: agent
}, function(response) {
response.on('end', function() {
assert.equal(1, agent.sockets['localhost:' + common.PORT].length);
assert.equal(agent.sockets[name].length, 1);
assert(!agent.requests.hasOwnProperty(name));
server.close();
});
});
request.end();
});
process.on('exit', function() {
assert(!agent.sockets.hasOwnProperty(name));
assert(!agent.requests.hasOwnProperty(name));
});

View File

@ -59,6 +59,7 @@ srv.listen(common.PORT, '127.0.0.1', function() {
'upgrade': 'websocket'
}
};
var name = options.host + ':' + options.port;
var req = http.request(options);
req.end();
@ -73,11 +74,11 @@ srv.listen(common.PORT, '127.0.0.1', function() {
'connection': 'upgrade',
'upgrade': 'websocket' };
assert.deepEqual(expectedHeaders, res.headers);
assert.equal(http.globalAgent.sockets[options.host + ':' + options.port].length, 1);
assert.equal(http.globalAgent.sockets[name].length, 1);
process.nextTick(function() {
// Make sure this request got removed from the pool.
assert.equal(http.globalAgent.sockets[options.host + ':' + options.port].length, 0);
assert(!http.globalAgent.sockets.hasOwnProperty(name));
socket.end();
srv.close();