From 6543f0959bd495b8b0326777034d6f13651dd4b3 Mon Sep 17 00:00:00 2001 From: MSP-Greg Date: Thu, 2 Jun 2022 13:10:03 -0500 Subject: [PATCH] Puma::ControlCLI - allow refork command to be sent as a request (#2868) * Puma::ControlCLI - allow refork command to be sent as a request * Puma::ControlCLI - add signal only commands * Puma::ControlCLI - check whether signal is available --- lib/puma/app/status.rb | 3 +++ lib/puma/control_cli.rb | 30 +++++++++++++++---------- lib/puma/launcher.rb | 11 +++++++++ test/test_integration_cluster.rb | 2 +- test/test_integration_pumactl.rb | 37 +++++++++++++++++++++++++++++++ test/test_pumactl.rb | 38 +++++++++++++++++++++++++++++++- 6 files changed, 107 insertions(+), 14 deletions(-) diff --git a/lib/puma/app/status.rb b/lib/puma/app/status.rb index 5cfb2b0b..7fe903cb 100644 --- a/lib/puma/app/status.rb +++ b/lib/puma/app/status.rb @@ -39,6 +39,9 @@ module Puma when 'phased-restart' @launcher.phased_restart ? 200 : 404 + when 'refork' + @launcher.refork ? 200 : 404 + when 'reload-worker-directory' @launcher.send(:reload_worker_directory) ? 200 : 404 diff --git a/lib/puma/control_cli.rb b/lib/puma/control_cli.rb index 23030962..859e5107 100644 --- a/lib/puma/control_cli.rb +++ b/lib/puma/control_cli.rb @@ -17,26 +17,30 @@ module Puma CMD_PATH_SIG_MAP = { 'gc' => nil, 'gc-stats' => nil, - 'halt' => 'SIGQUIT', - 'phased-restart' => 'SIGUSR1', - 'refork' => 'SIGURG', + 'halt' => 'SIGQUIT', + 'info' => 'SIGINFO', + 'phased-restart' => 'SIGUSR1', + 'refork' => 'SIGURG', 'reload-worker-directory' => nil, - 'restart' => 'SIGUSR2', + 'reopen-log' => 'SIGHUP', + 'restart' => 'SIGUSR2', 'start' => nil, 'stats' => nil, 'status' => '', - 'stop' => 'SIGTERM', - 'thread-backtraces' => nil + 'stop' => 'SIGTERM', + 'thread-backtraces' => nil, + 'worker-count-down' => 'SIGTTOU', + 'worker-count-up' => 'SIGTTIN' }.freeze # @deprecated 6.0.0 COMMANDS = CMD_PATH_SIG_MAP.keys.freeze # commands that cannot be used in a request - NO_REQ_COMMANDS = %w{refork}.freeze + NO_REQ_COMMANDS = %w[info reopen-log worker-count-down worker-count-up].freeze # @version 5.0.0 - PRINTABLE_COMMANDS = %w{gc-stats stats thread-backtraces}.freeze + PRINTABLE_COMMANDS = %w[gc-stats stats thread-backtraces].freeze def initialize(argv, stdout=STDOUT, stderr=STDERR) @state = nil @@ -185,8 +189,6 @@ module Puma if @command == 'status' message 'Puma is started' - elsif NO_REQ_COMMANDS.include? @command - raise "Invalid request command: #{@command}" else url = "/#{@command}" @@ -242,7 +244,11 @@ module Puma @stdout.flush unless @stdout.sync return elsif sig.start_with? 'SIG' - Process.kill sig, @pid + if Signal.list.key? sig.sub(/\ASIG/, '') + Process.kill sig, @pid + else + raise "Signal '#{sig}' not available'" + end elsif @command == 'status' begin Process.kill 0, @pid @@ -268,7 +274,7 @@ module Puma return start if @command == 'start' prepare_configuration - if Puma.windows? || @control_url + if Puma.windows? || @control_url && !NO_REQ_COMMANDS.include?(@command) send_request else send_signal diff --git a/lib/puma/launcher.rb b/lib/puma/launcher.rb index 7fc4652d..67e068d3 100644 --- a/lib/puma/launcher.rb +++ b/lib/puma/launcher.rb @@ -163,6 +163,17 @@ module Puma true end + # Begin a refork if supported + def refork + if clustered? && @runner.respond_to?(:fork_worker!) && @options[:fork_worker] + @runner.fork_worker! + true + else + log "* refork called but not available." + false + end + end + # Run the server. This blocks until the server is stopped def run previous_env = get_env diff --git a/test/test_integration_cluster.rb b/test/test_integration_cluster.rb index fde881ae..7fdd6e98 100644 --- a/test/test_integration_cluster.rb +++ b/test/test_integration_cluster.rb @@ -229,7 +229,7 @@ RUBY end # use three workers to keep accepting clients - def test_refork + def test_fork_worker_on_refork refork = Tempfile.new 'refork' wrkrs = 3 cli_server "-w #{wrkrs} test/rackup/hello_with_delay.ru", config: <