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.

Reply via email to