about summary refs log tree commit homepage
path: root/lib
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2013-11-01 00:04:59 +0000
committerEric Wong <normalperson@yhbt.net>2013-11-01 00:04:59 +0000
commit7c32323bdd375b1167b42991c081e3b579ad8243 (patch)
treed044e1a6810437d331e2f3d54c974ca45400877b /lib
parent885b2f28f3b31539140a8466e6205903bc7cf1d2 (diff)
downloadyahns-7c32323bdd375b1167b42991c081e3b579ad8243.tar.gz
It's conceivable a sub-optimally configured instance can have too
many Unix sockets connected to us.  This also implements expiry for
systems without sufficient "struct tcp_info" support.
Diffstat (limited to 'lib')
-rw-r--r--lib/yahns.rb1
-rw-r--r--lib/yahns/acceptor.rb7
-rw-r--r--lib/yahns/client_expire_generic.rb (renamed from lib/yahns/client_expire_portable.rb)17
-rw-r--r--lib/yahns/client_expire_tcpi.rb (renamed from lib/yahns/client_expire.rb)11
-rw-r--r--lib/yahns/http_client.rb1
-rw-r--r--lib/yahns/server.rb10
6 files changed, 34 insertions, 13 deletions
diff --git a/lib/yahns.rb b/lib/yahns.rb
index b493dc2..39747a8 100644
--- a/lib/yahns.rb
+++ b/lib/yahns.rb
@@ -61,7 +61,6 @@ require_relative 'yahns/queue_epoll'
 require_relative 'yahns/stream_input'
 require_relative 'yahns/tee_input'
 require_relative 'yahns/queue_egg'
-require_relative 'yahns/client_expire'
 require_relative 'yahns/http_response'
 require_relative 'yahns/http_client'
 require_relative 'yahns/http_context'
diff --git a/lib/yahns/acceptor.rb b/lib/yahns/acceptor.rb
index 2a212cf..c61975a 100644
--- a/lib/yahns/acceptor.rb
+++ b/lib/yahns/acceptor.rb
@@ -1,6 +1,8 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> et. al.
 # License: GPLv3 or later (see COPYING for details)
+require_relative 'client_expire_tcpi'
+require_relative 'client_expire_generic'
 module Yahns::Acceptor # :nodoc:
   def __ac_quit_done?
     @thrs.delete_if do |t|
@@ -62,4 +64,9 @@ module Yahns::Acceptor # :nodoc:
       end
     end
   end
+
+  def expire_mod
+    (Yahns::TCPServer === self && Yahns.const_defined?(:ClientExpireTCPI)) ?
+     Yahns::ClientExpireTCPI : Yahns::ClientExpireGeneric
+  end
 end
diff --git a/lib/yahns/client_expire_portable.rb b/lib/yahns/client_expire_generic.rb
index daf396c..f2f5369 100644
--- a/lib/yahns/client_expire_portable.rb
+++ b/lib/yahns/client_expire_generic.rb
@@ -1,19 +1,25 @@
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
-module Yahns::ClientExpire # :nodoc:
+module Yahns::ClientExpireGeneric # :nodoc:
   def __timestamp
     Time.now.to_f
   end
 
+  def yahns_init
+    super # Yahns::HttpClient#yahns_init
+    @last_io_at = 0
+  end
+
   def yahns_expire(timeout)
-    return 0 if closed? # still racy, but avoid the exception in most cases
+    return 0 if closed?
     if (__timestamp - @last_io_at) > timeout
       shutdown
       1
     else
       0
     end
-  rescue # the IO#closed? check is racy
+  # shutdown may race with the shutdown in http_response_done
+  rescue
     0
   end
 
@@ -31,4 +37,9 @@ module Yahns::ClientExpire # :nodoc:
     @last_io_at = __timestamp
     super
   end
+
+  def trysendfile(*args)
+    @last_io_at = __timestamp
+    super
+  end
 end
diff --git a/lib/yahns/client_expire.rb b/lib/yahns/client_expire_tcpi.rb
index 0a21c7b..8a89a42 100644
--- a/lib/yahns/client_expire.rb
+++ b/lib/yahns/client_expire_tcpi.rb
@@ -1,5 +1,6 @@
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+require 'raindrops'
 
 # included in Yahns::HttpClient
 #
@@ -7,7 +8,7 @@
 # on idle clients
 #
 # we absolutely DO NOT issue IO#close in here, only BasicSocket#shutdown
-module Yahns::ClientExpire # :nodoc:
+module Yahns::ClientExpireTCPI # :nodoc:
   def yahns_expire(timeout) # rarely called
     return 0 if closed?
 
@@ -31,10 +32,10 @@ module Yahns::ClientExpire # :nodoc:
     else
       0
     end
-  # we also do not expire UNIX domain sockets
-  # (since those are the most trusted of local clients)
-  # the IO#closed? check is racy
+  # shutdown may race with the shutdown in http_response_done
   rescue
     0
   end
-end
+# FreeBSD has "struct tcp_info", too, but does not support all the fields
+# Linux does as of FreeBSD 9 (haven't checked FreeBSD 10, yet).
+end if RUBY_PLATFORM =~ /linux/
diff --git a/lib/yahns/http_client.rb b/lib/yahns/http_client.rb
index 721be04..5f137fd 100644
--- a/lib/yahns/http_client.rb
+++ b/lib/yahns/http_client.rb
@@ -8,7 +8,6 @@ class Yahns::HttpClient < Kgio::Socket # :nodoc:
   Unicorn::HttpParser.keepalive_requests = 0xffffffff
 
   include Yahns::HttpResponse
-  include Yahns::ClientExpire
   QEV_FLAGS = Yahns::Queue::QEV_RD # used by acceptor
 
   # A frozen format for this is about 15% faster (note from Mongrel)
diff --git a/lib/yahns/server.rb b/lib/yahns/server.rb
index 330bcc8..4adf0c9 100644
--- a/lib/yahns/server.rb
+++ b/lib/yahns/server.rb
@@ -359,9 +359,12 @@ class Yahns::Server # :nodoc:
     @listeners.each do |l|
       opts = sock_opts(l)
       ctx = opts[:yahns_app_ctx]
+      ctx_list = opts[:yahns_app_ctx_list] ||= []
       qegg = ctx.qegg || @config.qeggs[:default]
       ctx.queue = queues[qegg] ||= qegg_vivify(qegg, fdmap)
-
+      ctx = ctx.dup
+      ctx.__send__(:include, l.expire_mod)
+      ctx_list << ctx
       # acceptors feed the the queues
       l.spawn_acceptor(opts[:threads] || 1, @logger, ctx)
     end
@@ -379,8 +382,9 @@ class Yahns::Server # :nodoc:
     drop_acceptors # stop acceptors, we close epolls in quit_done
     exit(0) unless alive # drop connections immediately if signaled twice
     @config.config_listeners.each_value do |opts|
-      ctx = opts[:yahns_app_ctx] or next
-      ctx.persistent_connections = false # Yahns::HttpContext
+      list= opts[:yahns_app_ctx_list] or next
+      # Yahns::HttpContext#persistent_connections=
+      list.each { |ctx| ctx.persistent_connections = false }
     end
     false
   end