From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.0 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 4F50120966 for ; Thu, 6 Apr 2017 05:15:29 +0000 (UTC) From: Eric Wong To: yahns-public@yhbt.net Subject: [PATCH] allow omitting specifying socket name when inheriting listen socket Date: Thu, 6 Apr 2017 05:15:29 +0000 Message-Id: <20170406051529.28129-1-e@80x24.org> List-Id: Since the common case is still to run a single app inside yahns, we can simplify setup a bit for systemd (and like) users by allowing them to omit the "listen" directive when they are running a single app in yahns. --- Documentation/yahns-rackup.pod | 4 ++++ lib/yahns/config.rb | 5 +++++ lib/yahns/rackup_handler.rb | 6 +++--- lib/yahns/server.rb | 4 +++- test/test_bin.rb | 47 +++++++++++++++++++++--------------------- 5 files changed, 39 insertions(+), 27 deletions(-) diff --git a/Documentation/yahns-rackup.pod b/Documentation/yahns-rackup.pod index 3fbde0e..de2d4b6 100644 --- a/Documentation/yahns-rackup.pod +++ b/Documentation/yahns-rackup.pod @@ -40,6 +40,10 @@ and PATH is meant to be a path to a UNIX domain socket. Defaults to "0.0.0.0:9292" (all addresses on TCP port 9292). Multiple addresses may be separated with commas. +For systemd users, a special value of "inherit" may be specified +to inherit FDs using the LISTEN_FDS and LISTEN_PID environment +variables described in L + =item -O stderr_path=PATHNAME Allow redirecting $stderr to a given path. Unlike doing this from diff --git a/lib/yahns/config.rb b/lib/yahns/config.rb index e545d59..bcea0d4 100644 --- a/lib/yahns/config.rb +++ b/lib/yahns/config.rb @@ -438,4 +438,9 @@ def commit!(server) @app_ctx.each { |app| app.logger ||= server.logger } end + + def register_inherited(name) + return unless @config_listeners.empty? && @app_ctx.size == 1 + @config_listeners[name] = { :yahns_app_ctx => @app_ctx[0] } + end end diff --git a/lib/yahns/rackup_handler.rb b/lib/yahns/rackup_handler.rb index 63ab373..3f217af 100644 --- a/lib/yahns/rackup_handler.rb +++ b/lib/yahns/rackup_handler.rb @@ -16,10 +16,10 @@ def self.run(app, o) # fine for most apps, but we have SIGUSR2 restarts to support working_directory(Yahns::START[:cwd]) - app(:rack, app) do + app(:rack, app) do # Yahns::Config#app addr = o[:listen] || "#{o[:Host]||default_host}:#{o[:Port]||8080}" - # allow listening to multiple addresses - addr.split(',').each { |l| listen(l) } + # allow listening to multiple addresses (Yahns::Config#listen) + addr.split(',').each { |l| listen(l) } unless addr == 'inherit' val = o[:client_timeout] and client_timeout(val) end diff --git a/lib/yahns/server.rb b/lib/yahns/server.rb index 43caae6..efd6f05 100644 --- a/lib/yahns/server.rb +++ b/lib/yahns/server.rb @@ -327,7 +327,9 @@ def inherit_listeners! opts = sock_opts(io) io = server_cast(io, opts) set_server_sockopt(io, opts) - @logger.info "inherited addr=#{sock_name(io)} fd=#{io.fileno}" + name = sock_name(io) + @logger.info "inherited addr=#{name} fd=#{io.fileno}" + @config.register_inherited(name) io end diff --git a/test/test_bin.rb b/test/test_bin.rb index 579e39c..e59c9b4 100644 --- a/test/test_bin.rb +++ b/test/test_bin.rb @@ -14,35 +14,36 @@ def setup 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(#{RbConfig.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"] + cmd = %W(#{RbConfig.ruby} -I lib bin/yahns-rackup -E none #{ru.path}) + [ %w(-O listen=inherit), %W(-p #{port} -o #{host}) ].each do |opt| + @srv.setsockopt(:SOL_SOCKET, :SO_KEEPALIVE, 0) + begin + pid = fork do # emulate a systemd environment + env = { 'LISTEN_PID' => $$.to_s, 'LISTEN_FDS' => '1' } + cmd.concat(opt) + 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 @srv.getsockopt(:SOL_SOCKET, :SO_KEEPALIVE).bool, + '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 + end end - - assert @srv.getsockopt(:SOL_SOCKET, :SO_KEEPALIVE).bool, - '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 -- EW