* [PATCH] emulate sd_listen_fds for systemd support
@ 2015-07-15 8:20 Eric Wong
0 siblings, 0 replies; only message in thread
From: Eric Wong @ 2015-07-15 8:20 UTC (permalink / raw)
To: yahns-public
systemd socket emulation shares FDs across execve, just like
the built-in SIGUSR2 upgrade process in unicorn. Thus it is
easy to support inheriting sockets from systemd.
---
lib/yahns/server.rb | 16 +++++++++++++---
test/test_bin.rb | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+), 3 deletions(-)
diff --git a/lib/yahns/server.rb b/lib/yahns/server.rb
index b6663e1..01334ca 100644
--- a/lib/yahns/server.rb
+++ b/lib/yahns/server.rb
@@ -312,12 +312,22 @@ class Yahns::Server # :nodoc:
# because that can completely break the non-blocking one.
# Unfortunately, there is no one-off MSG_DONTWAIT-like flag for
# accept4(2).
- inherited = ENV['YAHNS_FD'].to_s.split(',').map! do |fd|
- io = Socket.for_fd(fd.to_i)
+ inherited = ENV['YAHNS_FD'].to_s.split(',')
+
+ # emulate sd_listen_fds() for systemd
+ sd_pid, sd_fds = ENV.values_at('LISTEN_PID', 'LISTEN_FDS')
+ if sd_pid && sd_pid.to_i == $$
+ # 3 = SD_LISTEN_FDS_START
+ inherited.concat((3...(3 + sd_fds.to_i)).map { |fd| Socket.for_fd(fd) })
+ end
+ # to ease debugging, we will not unset LISTEN_PID and LISTEN_FDS
+
+ inherited.map! do |fd|
+ io = String === fd ? Socket.for_fd(fd.to_i) : fd
opts = sock_opts(io)
io = server_cast(io, opts)
set_server_sockopt(io, opts)
- @logger.info "inherited addr=#{sock_name(io)} fd=#{fd}"
+ @logger.info "inherited addr=#{sock_name(io)} fd=#{io.fileno}"
io
end
diff --git a/test/test_bin.rb b/test/test_bin.rb
index 8944eb3..b778a0d 100644
--- a/test/test_bin.rb
+++ b/test/test_bin.rb
@@ -11,6 +11,40 @@ class TestBin < Testcase
@cmd = %W(ruby -I lib bin/yahns)
end
+ def test_listen_fd3
+ return unless RUBY_VERSION.to_f > 2.3 # Fixed in ruby/trunk r51209, actually
+ @srv.setsockopt(:SOL_SOCKET, :SO_KEEPALIVE, 0)
+ host, port = @srv.addr[3], @srv.addr[1]
+
+ ru = tmpfile(%w(test_bin_daemon .ru))
+ ru.write("require 'rack/lobster'; run Rack::Lobster.new\n")
+ cmd = %W(ruby -I lib bin/yahns-rackup
+ -E none -p #{port} -o #{host} #{ru.path})
+ pid = fork do # emulate a systemd environment
+ env = {
+ 'LISTEN_PID' => $$.to_s,
+ 'LISTEN_FDS' => '1',
+ }
+ exec env, *cmd, 3 => @srv, err: @err.path
+ end
+ Net::HTTP.start(host, port) do |http|
+ req = Net::HTTP::Get.new("/")
+ res = http.request(req)
+ assert_equal 200, res.code.to_i
+ assert_equal "keep-alive", res["Connection"]
+ end
+
+ assert_equal 1, @srv.getsockopt(:SOL_SOCKET, :SO_KEEPALIVE).int,
+ 'ensure the inheriting process applies TCP socket options'
+ ensure
+ if pid
+ Process.kill(:QUIT, pid)
+ _, status = Process.waitpid2(pid)
+ assert status.success?, status.inspect
+ end
+ ru.close! if ru
+ end
+
def test_bin_daemon_noworker_inherit
bin_daemon(false, true)
end
--
EW
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2015-07-15 8:20 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-15 8:20 [PATCH] emulate sd_listen_fds for systemd support Eric Wong
Code repositories for project(s) associated with this public inbox
https://yhbt.net/yahns.git/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).