Skip to content
This repository has been archived by the owner on Dec 7, 2018. It is now read-only.

reel 0.5.0: Reel::StateError: already processing a request when client is killed #150

Closed
rakvat opened this issue Jun 4, 2014 · 7 comments · Fixed by #162
Closed

reel 0.5.0: Reel::StateError: already processing a request when client is killed #150

rakvat opened this issue Jun 4, 2014 · 7 comments · Fixed by #162

Comments

@rakvat
Copy link

rakvat commented Jun 4, 2014

I have a minimal reel server copied from the "Subclass Form" reel example that does some work before sending the response.
When I run it with reel 0.5.0. and http 0.6.1, send curl requests to the server and do 'pkill -f curl' while requests are running, the reel server crashes with 'Reel::StateError: already processing a request'.
The same setup with reel 0.4.0 and http 0.5.0 does not crash.

@tarcieri
Copy link
Member

tarcieri commented Jun 4, 2014

This is due to the introduction of pipelining, which requires that you completely consume the request before trying to process the next.

Perhaps Reel should do this implicitly, or let you turn pipelining off.

Until then, you need to consume the entire request body.

@rakvat
Copy link
Author

rakvat commented Jun 4, 2014

Is there a way to make sure that the entire request body is consumed? Does this also work if a curl client is killed or a browser rendering a web application that uses a reel server as back-end refreshes at the "wrong" moment?

@tarcieri
Copy link
Member

tarcieri commented Jun 4, 2014

You can call #to_str on the body. There should probably be a #flush method that does the same thing (and an option to auto-flush)

@rakvat
Copy link
Author

rakvat commented Jun 4, 2014

As far as I understand calling to_str on the body does not help as the server crashes before accessing the body. (Line 14 in the following gist: https://gist.github.com/rakvat/b0ff391fdd531873c8f6)

@tarcieri
Copy link
Member

tarcieri commented Jun 4, 2014

The first request doesn't go through?

My guess is you're trying to read the next request before the first request's body has been consumed.

@myronmarston
Copy link

I'm seeing similar behavior. I tried out your barebones hello world example and hit it with apache bench to try out some concurrency. It crashed:

*** Starting server on http://127.0.0.1:1234
E, [2014-06-06T17:09:33.156908 #27473] ERROR -- : Reel::Server::HTTP crashed!
Reel::StateError: already processing a request
    /Users/myron/moz/shares_r_us/bundle/ruby/2.1.0/gems/reel-0.5.0/lib/reel/connection.rb:55:in `request'
    /Users/myron/moz/shares_r_us/bundle/ruby/2.1.0/gems/reel-0.5.0/lib/reel/connection.rb:72:in `each_request'
    lib/reel_example.rb:13:in `block in <main>'
    /Users/myron/moz/shares_r_us/bundle/ruby/2.1.0/gems/reel-0.5.0/lib/reel/server.rb:56:in `call'
    /Users/myron/moz/shares_r_us/bundle/ruby/2.1.0/gems/reel-0.5.0/lib/reel/server.rb:56:in `handle_connection'
    /Users/myron/moz/shares_r_us/bundle/ruby/2.1.0/gems/celluloid-0.15.2/lib/celluloid/calls.rb:25:in `public_send'
    /Users/myron/moz/shares_r_us/bundle/ruby/2.1.0/gems/celluloid-0.15.2/lib/celluloid/calls.rb:25:in `dispatch'
    /Users/myron/moz/shares_r_us/bundle/ruby/2.1.0/gems/celluloid-0.15.2/lib/celluloid/calls.rb:122:in `dispatch'
    /Users/myron/moz/shares_r_us/bundle/ruby/2.1.0/gems/celluloid-0.15.2/lib/celluloid/actor.rb:322:in `block in handle_message'
    /Users/myron/moz/shares_r_us/bundle/ruby/2.1.0/gems/celluloid-0.15.2/lib/celluloid/actor.rb:416:in `block in task'
    /Users/myron/moz/shares_r_us/bundle/ruby/2.1.0/gems/celluloid-0.15.2/lib/celluloid/tasks.rb:55:in `block in initialize'
    /Users/myron/moz/shares_r_us/bundle/ruby/2.1.0/gems/celluloid-0.15.2/lib/celluloid/tasks/task_fiber.rb:13:in `block in create'
W, [2014-06-06T17:09:33.157470 #27473]  WARN -- : Terminating task: type=:call, meta={:method_name=>:run}, status=:iowait

I tried adding request.body.to_str as recommended here and it didn't help.

@rakvat
Copy link
Author

rakvat commented Jun 8, 2014

I debugged the issue with reel-0.5.0 and option spy: true. (The setup is still parallel curl requests, pkill -f curl, reel crashes.) There are many requests going through before I kill curl. The normal flow in lib/reel/connection.rb is 1) client connects, 2) initialize sets current_request to nil, 3) each_request calls request which sets current_request to a request object, 4) connection#respond gets called which calls current_request.handle_response and then resets current_request to nil.

When I kill curl (simulating a browser refresh) the flow in connection.rb is 1), 2), 3) as above, 4) current_request.handle_response raises a Broken Pipe Exception. Thus current_request is not reset to nil. The next time each_request calls request a StateError is raised as current_request is not nil.

I hope this helps.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants