Skip to content

Commit

Permalink
More elaborate exception handling. (puma#2700)
Browse files Browse the repository at this point in the history
* More elaborate exception handling. Fixes puma#2699.

* Add TestIntegrationSingle#test_closed_listener

Co-authored-by: MSP-Greg <Greg.mpls@gmail.com>
  • Loading branch information
2 people authored and JuanitoFatas committed Sep 9, 2022
1 parent 6d8ca64 commit 3c2dbab
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 3 deletions.
5 changes: 4 additions & 1 deletion lib/puma/server.rb
Expand Up @@ -356,7 +356,10 @@ def handle_servers
pool << client
end
end
rescue Object => e
rescue IOError, Errno::EBADF
# In the case that any of the sockets are unexpectedly close.
raise
rescue StandardError => e
@events.unknown_error e, nil, "Listen loop"
end
end
Expand Down
8 changes: 6 additions & 2 deletions test/helpers/integration.rb
Expand Up @@ -50,7 +50,7 @@ def silent_and_checked_system_command(*args)
assert(system(*args, out: File::NULL, err: File::NULL))
end

def cli_server(argv, unix: false, config: nil)
def cli_server(argv, unix: false, config: nil, merge_err: false)
if config
config_file = Tempfile.new(%w(config .rb))
config_file.write config
Expand All @@ -64,7 +64,11 @@ def cli_server(argv, unix: false, config: nil)
@tcp_port = UniquePort.call
cmd = "#{BASE} #{puma_path} #{config} -b tcp://#{HOST}:#{@tcp_port} #{argv}"
end
@server = IO.popen(cmd, "r")
if merge_err
@server = IO.popen(cmd, "r", :err=>[:child, :out])
else
@server = IO.popen(cmd, "r")
end
wait_for_server_to_boot
@pid = @server.pid
@server
Expand Down
6 changes: 6 additions & 0 deletions test/rackup/close_listeners.ru
@@ -0,0 +1,6 @@
require 'objspace'

run lambda { |env|
ios = ObjectSpace.each_object(::TCPServer).to_a.tap { |a| a.each(&:close) }
[200, [], ["#{ios.inspect}\n"]]
}
25 changes: 25 additions & 0 deletions test/test_integration_single.rb
Expand Up @@ -178,4 +178,29 @@ def test_application_logs_are_flushed_on_write
@server.close unless @server.closed?
@server = nil
end

# listener is closed 'externally' while Puma is in the IO.select statement
def test_closed_listener
skip_unless_signal_exist? :TERM

cli_server "test/rackup/close_listeners.ru", merge_err: true
read_body connect

begin
Timeout.timeout(5) do
begin
Process.kill :SIGTERM, @pid
rescue Errno::ESRCH
end
begin
Process.wait2 @pid
rescue Errno::ECHILD
end
end
rescue Timeout::Error
Process.kill :SIGKILL, @pid
assert false, "Process froze"
end
assert true
end
end

0 comments on commit 3c2dbab

Please sign in to comment.