Hi, I got more details about the issue and was able to replicate the
issue. It happens both with JRuby and MRI and I'm not sure whether it's
a Puma problem or not because I don't know other threaded server to test
with...
I created a new very simple Rails 4.1.5 with actioncontroller/railties
required in application.rb.
Basically, this is the controller:
main_controller.rb:
require 'timeout'
class MainController < ApplicationController
include ActionController::Live
CHUNK = ('a' * 1_000_000).freeze
def index
logger.info 'outside timeout block'
Timeout::timeout(5) do
logger.info 'inside timeout block'
10.times do |i|
20.times{response.stream.write "#{CHUNK}\n"}
sleep 1
end
end
logger.info 'timeout returned without errors'
rescue
logger.error "timeout rescue inside controller\n\n"
ensure
logger.error 'closing stream'
Thread.current.exit
# response.stream.close # this would block
# logger.info 'stream closed'
end
end
application_controller.rb:
require 'timeout'
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
def process(*args)
Timeout::timeout(5) do
super
end
rescue
logger.error "timeout happened!\n\n\n"
raise 'error'
end
end
Now, Rails will use a sized queue of size 10 for resonse.stream buffer.
That's why I write 20 times.
Puma is used to serve the application in production mode with default
settings (16 threads at most):
Now, I open an IRB session to simulate connections open by the client
but then have been lost for any reason:
require 'socket'
20.times{s = TCPSocket.new 'localhost', 3000; s.puts "GET /
HTTP/1.1\r\n\r\n";s.gets; s.close}
I can see 16 entries in the log and then the application stops
responding. I can see all error logs but with JRuby I can see the
threads still alive and waiting on object monitor inspecting a thread
dump using the VisualVM tool. I'm not sure how to inspect threads in MRI
but most probably the same happens with MRI as Puma also stops
responding there too.
Any ideas on what is happening? Is this a Rails bug, a Rack bug or a
Puma bug? How to handle such scenario? It seems the problem is that the
connection is lost while the Rails app is trying to write to the buffer.
Maybe Rails should use another SizedQueue implementation that would
accept some timeout if this is what's causing the issue (I tried to
raise an error, terminate the current thread (Thread.current.exit) and
to call close on the stream but none helped).
How can I debug this further to understand who is preventing the created
threads from being terminated?
Thanks in advance,
Rodrigo.
--
You received this message because you are subscribed to the Google Groups "Ruby on
Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to rubyonrails-core+unsubscr...@googlegroups.com.
To post to this group, send email to rubyonrails-core@googlegroups.com.
Visit this group at http://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/d/optout.