Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Bugfix: libeio race condition

Process at most 10 pending responses from the thread pool in one go.
10 was chosen arbitrarily.
Test and report by Felix Geisendörfer <felix@debuggable.com>
  • Loading branch information...
commit 0d7e88a4298740751bf0e8dabf9015baf88f455a 1 parent 3d24e11
@ry ry authored
Showing with 66 additions and 0 deletions.
  1. +3 −0  src/node.cc
  2. +63 −0 test/mjsunit/test-eio-race.js
View
3  src/node.cc
@@ -949,6 +949,9 @@ int main(int argc, char *argv[]) {
ev_async_init(&node::eio_watcher, node::EIOCallback);
// 2. Actaully start the thread pool.
eio_init(node::EIOWantPoll, NULL);
+ // Don't handle more than 10 reqs on each eio_poll(). This is to avoid
+ // race conditions. See test/mjsunit/test-eio-race.js
+ eio_set_max_poll_reqs(10);
// 3. Start watcher.
ev_async_start(EV_DEFAULT_UC_ &node::eio_watcher);
// 4. Remove a reference to the async watcher. This means we'll drop out
View
63 test/mjsunit/test-eio-race.js
@@ -0,0 +1,63 @@
+process.mixin(require("./common"));
+
+var
+ count = 100,
+ posix = require('posix');
+
+function tryToKillEventLoop() {
+ puts('trying to kill event loop ...');
+
+ posix.stat(__filename)
+ .addCallback(function() {
+ puts('first posix.stat succeeded ...');
+
+ posix.stat(__filename)
+ .addCallback(function() {
+ puts('second posix.stat succeeded ...');
+ puts('could not kill event loop, retrying...');
+
+ setTimeout(function () {
+ if (--count) {
+ tryToKillEventLoop();
+ } else {
+ process.exit(0);
+ }
+ }, 1);
+ })
+ .addErrback(function() {
+ throw new Exception('second posix.stat failed')
+ })
+
+ })
+ .addErrback(function() {
+ throw new Exception('first posix.stat failed')
+ });
+}
+
+// Generate a lot of thread pool events
+var pos = 0;
+posix.open('/dev/zero', process.O_RDONLY, 0666).addCallback(function (rd) {
+ function readChunk () {
+ posix.read(rd, 1024, pos, 'binary').addCallback(function (chunk, bytesRead) {
+ if (chunk) {
+ pos += bytesRead;
+ //puts(pos);
+ readChunk();
+ } else {
+ posix.close(rd);
+ throw new Exception(BIG_FILE+' should not end before the issue shows up');
+ }
+ }).addErrback(function () {
+ throw new Exception('could not read from '+BIG_FILE);
+ });
+ }
+ readChunk();
+}).addErrback(function () {
+ throw new Exception('could not open '+BIG_FILE);
+});
+
+tryToKillEventLoop();
+
+process.addListener("exit", function () {
+ assert.ok(pos > 10000);
+});
Please sign in to comment.
Something went wrong with that request. Please try again.