Module-level EMFILE handling
All net servers now share the same dummy socket. The ulimit warning is throttled for all servers.
This commit is contained in:
parent
899fffa395
commit
74d0a077ec
75
lib/net.js
75
lib/net.js
@ -958,8 +958,8 @@ function Server (/* [ options, ] listener */) {
|
|||||||
self.watcher.host = self;
|
self.watcher.host = self;
|
||||||
self.watcher.callback = function () {
|
self.watcher.callback = function () {
|
||||||
// Just in case we don't have a dummy fd.
|
// Just in case we don't have a dummy fd.
|
||||||
if (!self._dummyFD) self._getDummyFD();
|
getDummyFD();
|
||||||
|
|
||||||
if (self._acceptTimer) {
|
if (self._acceptTimer) {
|
||||||
// Somehow the watcher got started again. Need to wait until
|
// Somehow the watcher got started again. Need to wait until
|
||||||
// the timer finishes.
|
// the timer finishes.
|
||||||
@ -972,20 +972,10 @@ function Server (/* [ options, ] listener */) {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.errno != EMFILE) throw 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
|
// Gracefully reject pending clients by freeing up a file
|
||||||
// descriptor.
|
// descriptor.
|
||||||
if (self._dummyFD) {
|
rescueEMFILE(function() {
|
||||||
close(self._dummyFD); // Free up an fd
|
var acceptCount = 0;
|
||||||
self._dummyFD = null;
|
|
||||||
// Accept and close the waiting clients one at a time.
|
// Accept and close the waiting clients one at a time.
|
||||||
// Single threaded programming ftw.
|
// Single threaded programming ftw.
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -1006,9 +996,8 @@ function Server (/* [ options, ] listener */) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Reacquire the dummy fd
|
});
|
||||||
self._getDummyFD();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!peerInfo) return;
|
if (!peerInfo) return;
|
||||||
@ -1131,22 +1120,11 @@ Server.prototype._startWatcher = function () {
|
|||||||
this.emit("listening");
|
this.emit("listening");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Server.prototype._getDummyFD = function () {
|
|
||||||
try {
|
|
||||||
this._dummyFD = socket("tcp");
|
|
||||||
} catch (e) {
|
|
||||||
this._dummyFD = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Server.prototype._doListen = function () {
|
Server.prototype._doListen = function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
// Grab a dummy fd for EMFILE conditions.
|
// Ensure we have a dummy fd for EMFILE conditions.
|
||||||
self._getDummyFD();
|
getDummyFD();
|
||||||
self._lastEMFILEWarning = 0;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
bind(self.fd, arguments[0], arguments[1]);
|
bind(self.fd, arguments[0], arguments[1]);
|
||||||
@ -1189,11 +1167,6 @@ Server.prototype.close = function () {
|
|||||||
close(self.fd);
|
close(self.fd);
|
||||||
self.fd = null;
|
self.fd = null;
|
||||||
|
|
||||||
if (this._dummyFD) {
|
|
||||||
close(this._dummyFD);
|
|
||||||
this._dummyFD = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.type === "unix") {
|
if (self.type === "unix") {
|
||||||
fs.unlink(self.path, function () {
|
fs.unlink(self.path, function () {
|
||||||
self.emit("close");
|
self.emit("close");
|
||||||
@ -1202,3 +1175,33 @@ Server.prototype.close = function () {
|
|||||||
self.emit("close");
|
self.emit("close");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user