about summary refs log tree commit homepage
path: root/lib/yahns/client_expire_tcpi.rb
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/yahns/client_expire_tcpi.rb
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/yahns/client_expire_tcpi.rb')
-rw-r--r--lib/yahns/client_expire_tcpi.rb41
1 files changed, 41 insertions, 0 deletions
diff --git a/lib/yahns/client_expire_tcpi.rb b/lib/yahns/client_expire_tcpi.rb
new file mode 100644
index 0000000..8a89a42
--- /dev/null
+++ b/lib/yahns/client_expire_tcpi.rb
@@ -0,0 +1,41 @@
+# 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
+#
+# this provides the ability to expire idle clients once we hit a soft limit
+# on idle clients
+#
+# we absolutely DO NOT issue IO#close in here, only BasicSocket#shutdown
+module Yahns::ClientExpireTCPI # :nodoc:
+  def yahns_expire(timeout) # rarely called
+    return 0 if closed?
+
+    info = Raindrops::TCP_Info.new(self)
+    return 0 if info.state != 1 # TCP_ESTABLISHED == 1
+
+    # Linux struct tcp_info timers are in milliseconds
+    timeout *= 1000
+
+    send_timedout = !!(info.last_data_sent > timeout)
+
+    # tcpi_last_data_recv is not valid unless tcpi_ato (ACK timeout) is set
+    if 0 == info.ato
+      sd = send_timedout && (info.last_ack_recv > timeout)
+    else
+      sd = send_timedout && (info.last_data_recv > timeout)
+    end
+    if sd
+      shutdown
+      1
+    else
+      0
+    end
+  # shutdown may race with the shutdown in http_response_done
+  rescue
+    0
+  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/