diff options
Diffstat (limited to 'lib/yahns/acceptor.rb')
-rw-r--r-- | lib/yahns/acceptor.rb | 75 |
1 files changed, 44 insertions, 31 deletions
diff --git a/lib/yahns/acceptor.rb b/lib/yahns/acceptor.rb index 76fcc26..268393c 100644 --- a/lib/yahns/acceptor.rb +++ b/lib/yahns/acceptor.rb @@ -3,48 +3,61 @@ # License: GPLv3 or later (see COPYING for details) module Yahns::Acceptor # :nodoc: def __ac_quit_done? - @thr.join(0.01) ? close.nil? : false - rescue - @thr.alive? ? false : close.nil? + @thrs.delete_if do |t| + begin + t.join(0.01) + rescue + ! t.alive? + end + end + return false if @thrs[0] + close + true end # just keep looping this on every acceptor until the associated thread dies def ac_quit - @thr[:yahns_quit] = true + @thrs.each { |t| t[:yahns_quit] = true } return true if __ac_quit_done? - # try to connect to kick it out of the blocking accept() syscall - killer = Kgio::Socket.start(getsockname) - killer.kgio_write("G") # first byte of "GET / HTTP/1.0\r\n\r\n" + @thrs.each do + begin + # try to connect to kick it out of the blocking accept() syscall + killer = Kgio::Socket.start(getsockname) + killer.kgio_write("G") # first byte of "GET / HTTP/1.0\r\n\r\n" + ensure + killer.close if killer + end + end false # now hope __ac_quit_done? is true next time around rescue SystemCallError - __ac_quit_done? - ensure - killer.close if killer + return __ac_quit_done? end - def spawn_acceptor(logger, client_class, queue) - @thr = Thread.new do - t = Thread.current - accept_flags = Kgio::SOCK_NONBLOCK | Kgio::SOCK_CLOEXEC - qev_flags = client_class.superclass::QEV_FLAGS - begin - # We want the accept/accept4 syscall to be _blocking_ - # so it can distribute work evenly between processes - if client = kgio_accept(client_class, accept_flags) - client.yahns_init + def spawn_acceptor(nr, logger, client_class, queue) + @thrs = nr.times.map do + Thread.new do + t = Thread.current + accept_flags = Kgio::SOCK_NONBLOCK | Kgio::SOCK_CLOEXEC + qev_flags = client_class.superclass::QEV_FLAGS + begin + # We want the accept/accept4 syscall to be _blocking_ + # so it can distribute work evenly between processes + if client = kgio_accept(client_class, accept_flags) + client.yahns_init - # it is not safe to touch client in this thread after this, - # a worker thread may grab client right away - queue.queue_add(client, qev_flags) - end - rescue Errno::EMFILE, Errno::ENFILE => e - logger.error("#{e.message}, consider raising open file limits") - queue.fdmap.desperate_expire_for(nil, 5) - sleep 1 # let other threads do some work - rescue => e - Yahns::Log.exception(logger, "accept loop", e) - end until t[:yahns_quit] + # it is not safe to touch client in this thread after this, + # a worker thread may grab client right away + queue.queue_add(client, qev_flags) + end + rescue Errno::EMFILE, Errno::ENFILE => e + logger.error("#{e.message}, consider raising open file limits") + queue.fdmap.desperate_expire_for(nil, 5) + sleep 1 # let other threads do some work + rescue => e + Yahns::Log.exception(logger, "accept loop", e) + end until t[:yahns_quit] + end end end end |