Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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.
  • Loading branch information...
commit 0ac2ef924f2564ab967be22c7b4ae18c20ff4fc2 1 parent 9bf2975
@ry ry authored
Showing with 24 additions and 1 deletion.
  1. +1 −0  TODO
  2. +23 −1 lib/net.js
View
1  TODO
@@ -25,3 +25,4 @@
based on size but rather read until EOF into a chain of buffers, then
concat them together.
- process object should be defined in src/node.js not in c++
+- Test for EMFILE accept spin bug.
View
24 lib/net.js
@@ -1049,6 +1049,25 @@ function Server (listener) {
self.connections = 0;
+ self.paused = false;
+ self.pauseTimeout = 1000;
+
+ 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 () {
@@ -1056,7 +1075,10 @@ function Server (listener) {
try {
var peerInfo = accept(self.fd);
} catch (e) {
- if (e.errno == EMFILE) return;
+ if (e.errno == EMFILE) {
+ pause();
+ return;
+ }
throw e;
}
if (!peerInfo) return;
Please sign in to comment.
Something went wrong with that request. Please try again.