diff --git a/benchmark/idle_clients.js b/benchmark/idle_clients.js index edeb641ac1..9bb7862807 100644 --- a/benchmark/idle_clients.js +++ b/benchmark/idle_clients.js @@ -17,7 +17,7 @@ function connect () { s.on('close', function () { if (gotConnected) connections--; - if (!haderror) connect(); + //if (!haderror) connect(); }); s.on('end', function () { @@ -36,6 +36,9 @@ connect(); var oldConnections, oldErrors; +// Try to start new connections every so often +setInterval(connect, 5000); + setInterval(function () { if (oldConnections != connections) { oldConnections = connections; diff --git a/lib/net.js b/lib/net.js index f25012364d..1e11c4aa2e 100644 --- a/lib/net.js +++ b/lib/net.js @@ -922,36 +922,38 @@ function Server (/* [ options, ] listener */) { self.connections = 0; - self.paused = false; - self.pauseTimeout = 1000; - self.allowHalfOpen = options.allowHalfOpen || false; - function pause () { - // We've hit the maximum file limit. What to do? - // Let's try again in 1 second. - self.watcher.stop(); - - // If we're already paused, don't do another timeout. - if (self.paused) return; - - setTimeout(function () { - self.paused = false; - // Make sure we haven't closed in the interim - if (typeof self.fd != 'number') return; - self.watcher.start(); - }, self.pauseTimeout); - } - self.watcher = new IOWatcher(); self.watcher.host = self; self.watcher.callback = function () { + // Just in case we don't have a dummy fd. + if (!self._dummyFD) self._getDummyFD(); + while (self.fd) { try { var peerInfo = accept(self.fd); } catch (e) { if (e.errno == EMFILE) { - pause(); + // Output a warning, but only at most every 5 seconds. + var now = new Date(); + if (now - self._lastEMFILEWarning > 5000) { + console.error("(node) Hit max file limit. Increase 'ulimit -n'."); + } + self._lastEMFILEWarning = now; + + // Gracefully reject pending clients by freeing up a file + // descriptor. + if (self._dummyFD) { + close(self._dummyFD); + self._dummyFD = null; + while (true) { + peerInfo = accept(self.fd); + if (!peerInfo) break; + close(peerInfo.fd); + } + self._getDummyFD(); + } return; } throw e; @@ -1076,9 +1078,23 @@ Server.prototype._startWatcher = function () { this.emit("listening"); }; + +Server.prototype._getDummyFD = function () { + try { + this._dummyFD = socket("tcp"); + } catch (e) { + this._dummyFD = null; + } +}; + + Server.prototype._doListen = function () { var self = this; + // Grab a dummy fd for EMFILE conditions. + self._getDummyFD(); + self._lastEMFILEWarning = 0; + try { bind(self.fd, arguments[0], arguments[1]); } catch (err) { @@ -1120,6 +1136,11 @@ Server.prototype.close = function () { close(self.fd); self.fd = null; + if (this._dummyFD) { + close(this._dummyFD); + this._dummyFD = null; + } + if (self.type === "unix") { fs.unlink(self.path, function () { self.emit("close");