[PATCH] possible MRI 1.8 thread fix to avoid blocking accept()

Eric Wong normalperson at yhbt.net
Mon Dec 21 19:54:21 EST 2009

Under MRI 1.8, listen sockets do not appear to have the
nonblocking I/O flag on by default, nor does it set the
nonblocking I/O flag when calling #accept (but it does
when using #accept_nonblock, of course).

Normally this is not a problem even when using green threads
since MRI will internally select(2) on the file descriptor
before attempting a blocking (and immediately successful)

However, when sharing a listen descriptor across multiple
processes, spurious wakeups are likely to occur, causing
multiple processes may be woken up when a single client

This causes a problem because accept(2)-ing on multiple
threads/processes for a single connection causes blocking accepts in
multiple processes, leading to stalled green threads.

This is not an issue under 1.9 where a blocking accept() call
unlocks the GVL to let other threads run.
  I just pushed this out to git://git.bogomips.org/rainbows.git, too.
  Testers appreciated, thanks.

  Eric Wong <normalperson at yhbt.net> wrote:
  > I've heard (privately) about issues with accept() somehow blocking the
  > entire worker process under 1.8.  Obviously this really should not
  > happen, but I'm unable to reproduce it myself.

 lib/rainbows/base.rb |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/lib/rainbows/base.rb b/lib/rainbows/base.rb
index 211b41c..4a4d076 100644
--- a/lib/rainbows/base.rb
+++ b/lib/rainbows/base.rb
@@ -14,6 +14,12 @@ module Rainbows
       G.tmp = worker.tmp
+      # avoid spurious wakeups and blocking-accept() with 1.8 green threads
+      if RUBY_VERSION.to_f < 1.8
+        require "io/nonblock"
+        LISTENERS.each { |l| l.nonblock = true }
+      end
       # we're don't use the self-pipe mechanism in the Rainbows! worker
       # since we don't defer reopening logs
       HttpServer::SELF_PIPE.each { |x| x.close }.clear
Eric Wong

More information about the rainbows-talk mailing list