celluloid / reel

UNMAINTAINED: See celluloid/celluloid#779 - Celluloid::IO-powered web server
https://celluloid.io
MIT License
596 stars 87 forks source link

Actor crashed upon run - subclassing Reel::Server::HTTP #183

Closed mistergibson closed 9 years ago

mistergibson commented 9 years ago
E, [2015-03-28T16:43:14.889391 #18019] ERROR -- : Actor crashed!
ArgumentError: this IO is already registered with selector
    /var/lib/gems/1.9.1/gems/celluloid-io-0.16.2/lib/celluloid/io/reactor.rb:42:in `register'
    /var/lib/gems/1.9.1/gems/celluloid-io-0.16.2/lib/celluloid/io/reactor.rb:42:in `wait'
    /var/lib/gems/1.9.1/gems/celluloid-io-0.16.2/lib/celluloid/io/reactor.rb:21:in `wait_readable'
    /var/lib/gems/1.9.1/gems/celluloid-io-0.16.2/lib/celluloid/io.rb:53:in `wait_readable'
    /var/lib/gems/1.9.1/gems/celluloid-io-0.16.2/lib/celluloid/io/tcp_server.rb:19:in `accept'
    /var/lib/gems/1.9.1/gems/reel-0.5.0/lib/reel/server.rb:38:in `block in run'
    /var/lib/gems/1.9.1/gems/reel-0.5.0/lib/reel/server.rb:38:in `loop'
    /var/lib/gems/1.9.1/gems/reel-0.5.0/lib/reel/server.rb:38:in `run'
    /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `public_send'
    /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `dispatch'
    /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/calls.rb:63:in `dispatch'
    /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/cell.rb:60:in `block in invoke'
    /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/cell.rb:71:in `block in task'
    /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/actor.rb:357:in `block in task'
    /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/tasks.rb:57:in `block in initialize'
    /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/tasks/task_fiber.rb:15:in `block in create'
W, [2015-03-28T16:43:14.890398 #18019]  WARN -- : Terminating task: type=:call, meta={:method_name=>:run}, status=:iowait
    Celluloid::TaskFiber backtrace unavailable. Please try `Celluloid.task_class = Celluloid::TaskThread` if you need backtraces here.
D, [2015-03-28T16:43:14.890031 #18019] DEBUG -- : Terminating 1 actor...
/var/lib/gems/1.9.1/gems/celluloid-io-0.16.2/lib/celluloid/io/reactor.rb:42:in `register': this IO is already registered with selector (ArgumentError)
    from /var/lib/gems/1.9.1/gems/celluloid-io-0.16.2/lib/celluloid/io/reactor.rb:42:in `wait'
    from /var/lib/gems/1.9.1/gems/celluloid-io-0.16.2/lib/celluloid/io/reactor.rb:21:in `wait_readable'
    from /var/lib/gems/1.9.1/gems/celluloid-io-0.16.2/lib/celluloid/io.rb:53:in `wait_readable'
    from /var/lib/gems/1.9.1/gems/celluloid-io-0.16.2/lib/celluloid/io/tcp_server.rb:19:in `accept'
    from /var/lib/gems/1.9.1/gems/reel-0.5.0/lib/reel/server.rb:38:in `block in run'
    from /var/lib/gems/1.9.1/gems/reel-0.5.0/lib/reel/server.rb:38:in `loop'
    from /var/lib/gems/1.9.1/gems/reel-0.5.0/lib/reel/server.rb:38:in `run'
    from /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `public_send'
    from /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `dispatch'
    from /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/calls.rb:63:in `dispatch'
    from /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/cell.rb:60:in `block in invoke'
    from /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/cell.rb:71:in `block in task'
    from /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/actor.rb:357:in `block in task'
    from /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/tasks.rb:57:in `block in initialize'
    from /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/tasks/task_fiber.rb:15:in `block in create'
    from (celluloid):0:in `remote procedure call'
    from /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/calls.rb:92:in `value'
    from /var/lib/gems/1.9.1/gems/celluloid-0.16.0/lib/celluloid/proxies/sync_proxy.rb:33:in `method_missing'
    from gxg-www-reel.rb:75:in `<main>'

Attempting this:

require 'json'
require 'base64'
require 'reel'

class Session
  def initialize()
    @sockets = []
  end
  #
  def handle_request(the_request)
    result = nil
    if the_request.websocket?
      # websocket
      unless the_request.websocket.closed?
        # respond to websocket request
        message = the_request.websocket.read()
        message = ::Base64::strict_decode64(message)
        message = ::JSON.parse(message)
        puts message.inspect
      end
    else
      # resources
      # process path
      buffer = nil
      the_path = File.expand_path("./public/#{the_request.path}",File.dirname(__FILE__))
      if File.exist?(the_path)
        # find resource files
        # load resource files
        buffer = ""
        the_file = File.open(the_path, "r")
        buffer << the_file.read()
        the_file.close()
      else
        result = "Not Found Error"
      end
      # respond with raw content
      if buffer
        result = buffer
      end
    end
    result
  end
  #
#
end
#
class Server < Reel::Server::HTTP
  def initialize(host = "127.0.0.1", port = 3000)
    @thread_safety = ::Mutex.new
    @session_pool = {}
    super(host, port, &method(:on_connection))
  end
  #
  def on_connection(connection)
    connection.each_request do |request|
      the_session = nil
      session_key = (connection.remote_host.to_s + "@" + connection.remote_ip.to_s).to_sym
      if @thread_safety.synchronize { @session_pool[(session_key)] }
        the_session = @thread_safety.synchronize { @session_pool[(session_key)] }
      else
        the_session = @thread_safety.synchronize { @session_pool[(session_key)] = Session.new }
      end
      if the_session
        response = the_session.handle_request(request)
        if response
          connection.respond(:ok, response)
        end
      end
      #
    end
  end
end
the_server = Server.new()
the_server.run 
digitalextremist commented 9 years ago

RVM? Version?

digitalextremist commented 9 years ago

I am running the repro now, but there must be a client side also that causes the crash?

digitalextremist commented 9 years ago

This happens with mri and rbx but not jruby

mistergibson commented 9 years ago

ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-linux]

digitalextremist commented 9 years ago

This is actually your error @mistergibson... the server is being instantiated twice on an IO level.

This works:

Server.run

Double check the documentation and notice, the server is not instantiated first, then run, it's just run, and it instantiates itself. So by instantiating it and then running it, you actually double-instantiate it.

mistergibson commented 9 years ago

Thanks for pointing that out - I'll check it.