From 47e1ee2d90161abf92ce14562bf508398fdfa6c9 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 25 Aug 2010 13:58:11 -0700 Subject: split out accept() callers to acceptor module Trying to avoid adding singleton methods since it's too easily accessible by the public and not needed by the general public. This also allows us (or just Zbatery) to more easily add support systems without FD_CLOEXEC or fcntl, and also to optimize away a fcntl call for systems that inherit FD_CLOEXEC. --- lib/rainbows.rb | 17 +---------------- lib/rainbows/acceptor.rb | 26 ++++++++++++++++++++++++++ lib/rainbows/event_machine.rb | 3 ++- lib/rainbows/fiber/rev.rb | 3 ++- lib/rainbows/fiber_pool.rb | 3 ++- lib/rainbows/fiber_spawn.rb | 3 ++- lib/rainbows/rev/core.rb | 3 ++- lib/rainbows/thread_pool.rb | 5 +++-- lib/rainbows/thread_spawn.rb | 3 ++- 9 files changed, 42 insertions(+), 24 deletions(-) create mode 100644 lib/rainbows/acceptor.rb diff --git a/lib/rainbows.rb b/lib/rainbows.rb index 52e7519..f80d5fd 100644 --- a/lib/rainbows.rb +++ b/lib/rainbows.rb @@ -75,22 +75,6 @@ module Rainbows HttpServer.new(app, options).start.join end - # returns nil if accept fails - def sync_accept(sock) # :nodoc: - rv = sock.accept - rv.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) - rv - rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EINTR - end - - # returns nil if accept fails - def accept(sock) # :nodoc: - rv = sock.accept_nonblock - rv.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) - rv - rescue Errno::EAGAIN, Errno::ECONNABORTED - end - # returns a string representing the address of the given client +io+ # For local UNIX domain sockets, this will return a string referred # to by the (non-frozen) Unicorn::HttpRequest::LOCALHOST constant. @@ -139,3 +123,4 @@ module Rainbows autoload :HttpResponse, 'rainbows/http_response' # deprecated autoload :ThreadTimeout, 'rainbows/thread_timeout' end +require 'rainbows/acceptor' diff --git a/lib/rainbows/acceptor.rb b/lib/rainbows/acceptor.rb new file mode 100644 index 0000000..c67bf20 --- /dev/null +++ b/lib/rainbows/acceptor.rb @@ -0,0 +1,26 @@ +# -*- encoding: binary -*- + +# :enddoc: +require 'fcntl' + +# this should make life easier for Zbatery if compatibility with +# fcntl-crippled platforms is required (or if FD_CLOEXEC is inherited) +# and we want to microptimize away fcntl(2) syscalls. +module Rainbows::Acceptor + + # returns nil if accept fails + def sync_accept(sock) + rv = sock.accept + rv.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) + rv + rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EINTR + end + + # returns nil if accept fails + def accept(sock) + rv = sock.accept_nonblock + rv.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) + rv + rescue Errno::EAGAIN, Errno::ECONNABORTED + end +end diff --git a/lib/rainbows/event_machine.rb b/lib/rainbows/event_machine.rb index a0b9ca6..2a41015 100644 --- a/lib/rainbows/event_machine.rb +++ b/lib/rainbows/event_machine.rb @@ -169,6 +169,7 @@ module Rainbows end module Server # :nodoc: all + include Rainbows::Acceptor def close detach @@ -177,7 +178,7 @@ module Rainbows def notify_readable return if CUR.size >= MAX - io = Rainbows.accept(@io) or return + io = accept(@io) or return sig = EM.attach_fd(io.fileno, false) CUR[sig] = CL.new(sig, io) end diff --git a/lib/rainbows/fiber/rev.rb b/lib/rainbows/fiber/rev.rb index c23d844..632b562 100644 --- a/lib/rainbows/fiber/rev.rb +++ b/lib/rainbows/fiber/rev.rb @@ -54,6 +54,7 @@ module Rainbows::Fiber include Rainbows include Rainbows::Const include Rainbows::Response + include Rainbows::Acceptor FIO = Rainbows::Fiber::IO def to_io @@ -72,7 +73,7 @@ module Rainbows::Fiber def on_readable return if G.cur >= MAX - c = Rainbows.accept(@io) and ::Fiber.new { process(c) }.resume + c = accept(@io) and ::Fiber.new { process(c) }.resume end def process(io) diff --git a/lib/rainbows/fiber_pool.rb b/lib/rainbows/fiber_pool.rb index 42f6dbe..63f1e2e 100644 --- a/lib/rainbows/fiber_pool.rb +++ b/lib/rainbows/fiber_pool.rb @@ -15,6 +15,7 @@ module Rainbows module FiberPool include Fiber::Base + include Rainbows::Acceptor def worker_loop(worker) # :nodoc: init_worker_process(worker) @@ -29,7 +30,7 @@ module Rainbows begin schedule do |l| fib = pool.shift or break # let another worker process take it - if io = Rainbows.accept(l) + if io = accept(l) fib.resume(Fiber::IO.new(io, fib)) else pool << fib diff --git a/lib/rainbows/fiber_spawn.rb b/lib/rainbows/fiber_spawn.rb index df72e70..ecf83d8 100644 --- a/lib/rainbows/fiber_spawn.rb +++ b/lib/rainbows/fiber_spawn.rb @@ -12,6 +12,7 @@ module Rainbows module FiberSpawn include Fiber::Base + include Rainbows::Acceptor def worker_loop(worker) # :nodoc: init_worker_process(worker) @@ -22,7 +23,7 @@ module Rainbows begin schedule do |l| break if G.cur >= limit - io = Rainbows.accept(l) or next + io = accept(l) or next ::Fiber.new { process_client(fio.new(io, ::Fiber.current)) }.resume end rescue => e diff --git a/lib/rainbows/rev/core.rb b/lib/rainbows/rev/core.rb index 9f7a1f0..9f20574 100644 --- a/lib/rainbows/rev/core.rb +++ b/lib/rainbows/rev/core.rb @@ -7,12 +7,13 @@ require 'rainbows/rev/heartbeat' module Rainbows module Rev class Server < ::Rev::IO + include Rainbows::Acceptor G = Rainbows::G # CL and MAX will be defined in the corresponding worker loop def on_readable return if CONN.size >= MAX - io = Rainbows.accept(@_io) and CL.new(io).attach(LOOP) + io = accept(@_io) and CL.new(io).attach(LOOP) end end # class Server diff --git a/lib/rainbows/thread_pool.rb b/lib/rainbows/thread_pool.rb index 28a943e..a643bd8 100644 --- a/lib/rainbows/thread_pool.rb +++ b/lib/rainbows/thread_pool.rb @@ -24,6 +24,7 @@ module Rainbows module ThreadPool include Base + include Rainbows::Acceptor def worker_loop(worker) # :nodoc: init_worker_process(worker) @@ -44,7 +45,7 @@ module Rainbows def sync_worker # :nodoc: s = LISTENERS[0] begin - c = Rainbows.sync_accept(s) and process_client(c) + c = sync_accept(s) and process_client(c) rescue => e Error.listen_loop(e) end while G.alive @@ -58,7 +59,7 @@ module Rainbows # problem. On the other hand, a thundering herd may not # even incur as much overhead as an extra Mutex#synchronize ret = IO.select(LISTENERS, nil, nil, 1) and ret[0].each do |s| - s = Rainbows.accept(s) and process_client(s) + s = accept(s) and process_client(s) end rescue Errno::EINTR rescue => e diff --git a/lib/rainbows/thread_spawn.rb b/lib/rainbows/thread_spawn.rb index 6952f26..0d4973a 100644 --- a/lib/rainbows/thread_spawn.rb +++ b/lib/rainbows/thread_spawn.rb @@ -18,6 +18,7 @@ module Rainbows module ThreadSpawn include Base + include Rainbows::Acceptor def accept_loop(klass) #:nodoc: lock = Mutex.new @@ -36,7 +37,7 @@ module Rainbows # CPU during I/O wait, CPU cycles that can be better used # by other worker _processes_. sleep(0.01) - elsif c = Rainbows.sync_accept(l) + elsif c = sync_accept(l) klass.new(c) do |c| begin lock.synchronize { G.cur += 1 } -- cgit v1.2.3-24-ge0c7