From ccd08435620d1d978c42506e4f30326ec6865eb8 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Wed, 15 Sep 2021 21:45:04 +1200 Subject: [PATCH] More elaborate exception handling. Fixes #2699. --- lib/puma/server.rb | 5 ++++- test/config/broken_io.rb | 9 +++++++++ test/test_broken_io.rb | 28 ++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 test/config/broken_io.rb create mode 100644 test/test_broken_io.rb diff --git a/lib/puma/server.rb b/lib/puma/server.rb index 1309eb8423..004294964f 100644 --- a/lib/puma/server.rb +++ b/lib/puma/server.rb @@ -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 diff --git a/test/config/broken_io.rb b/test/config/broken_io.rb new file mode 100644 index 0000000000..fb8762a713 --- /dev/null +++ b/test/config/broken_io.rb @@ -0,0 +1,9 @@ +require 'objspace' + +app do |env| + ios = ObjectSpace.each_object(IO).to_a.select {|io| io.is_a?(TCPServer)} + + ios.each(&:close) + + [200, [], [ios.inspect]] +end diff --git a/test/test_broken_io.rb b/test/test_broken_io.rb new file mode 100644 index 0000000000..716b2696bb --- /dev/null +++ b/test/test_broken_io.rb @@ -0,0 +1,28 @@ +require_relative "helper" +require_relative "helpers/integration" + +class TestBrokenIO < TestIntegration + def wait_for(pattern) + while line = @server.gets + if line =~ pattern + return true + end + end + end + + def test_broken_io + @tcp_port = UniquePort.call + + cli_server "-b tcp://#{HOST}:#{@tcp_port} -C test/config/broken_io.rb test/rackup/hello.ru" + + # Invoke a request which must be rejected + stdout_str, status = Open3.capture2("curl #{HOST}:#{@tcp_port}") + + Process.kill :INT , @pid + + wait_for(/Goodbye/) + + @server.close + @server = nil + end +end