Skip to content

Commit

Permalink
Module-level EMFILE handling
Browse files Browse the repository at this point in the history
All net servers now share the same dummy socket. The ulimit warning is
throttled for all servers.

Conflicts:

	lib/net.js
  • Loading branch information
ry committed Nov 16, 2010
1 parent 3c9746d commit 26b3f22
Showing 1 changed file with 37 additions and 36 deletions.
73 changes: 37 additions & 36 deletions lib/net.js
Original file line number Diff line number Diff line change
Expand Up @@ -1085,8 +1085,8 @@ function Server (listener) {
self.watcher.host = self;
self.watcher.callback = function () {
// Just in case we don't have a dummy fd.
if (!self._dummyFD) self._getDummyFD();

getDummyFD();
if (self._acceptTimer) {
// Somehow the watcher got started again. Need to wait until
// the timer finishes.
Expand All @@ -1099,20 +1099,10 @@ function Server (listener) {
} catch (e) {
if (e.errno != EMFILE) throw e;

// 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;
}

var acceptCount = 0;

// Gracefully reject pending clients by freeing up a file
// descriptor.
if (self._dummyFD) {
close(self._dummyFD); // Free up an fd
self._dummyFD = null;
rescueEMFILE(function() {
var acceptCount = 0;
// Accept and close the waiting clients one at a time.
// Single threaded programming ftw.
while (true) {
Expand All @@ -1133,9 +1123,8 @@ function Server (listener) {
break;
}
}
// Reacquire the dummy fd
self._getDummyFD();
}
});

return;
}
if (!peerInfo) return;
Expand Down Expand Up @@ -1265,20 +1254,9 @@ 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 () {
// Grab a dummy fd for EMFILE conditions.
this._getDummyFD();
this._lastEMFILEWarning = 0;
// Ensure we have a dummy fd for EMFILE conditions.
getDummyFD();

listen(this.fd, 128);
this._startWatcher();
Expand All @@ -1300,11 +1278,6 @@ 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");
Expand All @@ -1314,4 +1287,32 @@ Server.prototype.close = function () {
}
};

// vim:ts=2 sw=2
var dummyFD = null;
var lastEMFILEWarning = 0;
// Ensures to have at least on free file-descriptor free.
// callback should only use 1 file descriptor and close it before end of call
function rescueEMFILE(callback) {
// Output a warning, but only at most every 5 seconds.
var now = new Date();
if (now - lastEMFILEWarning > 5000) {
console.error("(node) Hit max file limit. Increase 'ulimit -n'.");
lastEMFILEWarning = now;
}

if (dummyFD) {
close(dummyFD);
dummyFD = null;
callback();
getDummyFD();
}
}

function getDummyFD() {
if (!dummyFD) {
try {
dummyFD = socket("tcp");
} catch (e) {
dummyFD = null;
}
}
}

0 comments on commit 26b3f22

Please sign in to comment.