From ee7fe220ccbc991e1e7cbe982caf48e3303274c7 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 21 Dec 2009 16:31:28 -0800 Subject: possible MRI 1.8 thread fix to avoid blocking accept() 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) accept(2). 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 connects. 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. --- lib/rainbows/base.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib/rainbows/base.rb') 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 super(worker) 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 -- cgit v1.2.3-24-ge0c7