Skip to content

Commit 0ac2ef9

Browse files
committed
Do not spin on aceept() with EMFILE
When a server hit EMFILE it would continue to try to accept new connections from the queue. This patch introduces a timeout of one second where it will stop trying to accept new files. After the second is over it tries again. This is a rather serious bug that has been effecting many highly concurrent programs. It was introduced in 4593c0, version v0.2.0. TODO: A test for this situation. Currently I test it like this termA% cd projects/node termA% ulimit -n 256 termA% ./node benchmark/idle_server.js termB% cd projects/node termB% ./node benchmark/idle_clients.js And watch how the server process behaves.
1 parent 9bf2975 commit 0ac2ef9

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

TODO

+1
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@
2525
based on size but rather read until EOF into a chain of buffers, then
2626
concat them together.
2727
- process object should be defined in src/node.js not in c++
28+
- Test for EMFILE accept spin bug.

lib/net.js

+23-1
Original file line numberDiff line numberDiff line change
@@ -1049,14 +1049,36 @@ function Server (listener) {
10491049

10501050
self.connections = 0;
10511051

1052+
self.paused = false;
1053+
self.pauseTimeout = 1000;
1054+
1055+
function pause () {
1056+
// We've hit the maximum file limit. What to do?
1057+
// Let's try again in 1 second.
1058+
self.watcher.stop();
1059+
1060+
// If we're already paused, don't do another timeout.
1061+
if (self.paused) return;
1062+
1063+
setTimeout(function () {
1064+
self.paused = false;
1065+
// Make sure we haven't closed in the interim
1066+
if (typeof self.fd != 'number') return;
1067+
self.watcher.start();
1068+
}, self.pauseTimeout);
1069+
}
1070+
10521071
self.watcher = new IOWatcher();
10531072
self.watcher.host = self;
10541073
self.watcher.callback = function () {
10551074
while (self.fd) {
10561075
try {
10571076
var peerInfo = accept(self.fd);
10581077
} catch (e) {
1059-
if (e.errno == EMFILE) return;
1078+
if (e.errno == EMFILE) {
1079+
pause();
1080+
return;
1081+
}
10601082
throw e;
10611083
}
10621084
if (!peerInfo) return;

0 commit comments

Comments
 (0)