Skip to content

Instantly share code, notes, and snippets.

@lmarburger
Created May 26, 2011 21:16
Show Gist options
  • Save lmarburger/994107 to your computer and use it in GitHub Desktop.
Save lmarburger/994107 to your computer and use it in GitHub Desktop.
Handling exceptions with thin, eventmachine, and em-http-request.
require 'rubygems'
require 'eventmachine'
require 'fiber'
EM.error_handler { |e| p "EM.error_handler: #{ e.message }" }
run(lambda do |env|
case env['PATH_INFO']
###
# Hits EM.error_handler
#
# $ bundle exec thin start
# >> Using rack adapter
# >> Thin web server (v1.2.11 codename Bat-Shit Crazy)
# >> Maximum connections set to 1024
# >> Listening on 0.0.0.0:3000, CTRL+C to stop
# "yielding"
# "throwing"
# "done sleeping"
# "EM.error_handler: die"
when '/sleep'
Fiber.new do
fiber = Fiber.current
EM::Timer.new(1) { p 'done sleeping'; fiber.resume }
p 'yielding'
Fiber.yield
raise 'die'
end.resume
p 'throwing'
throw :async
###
# Crashes app server using eventmachine 0.12.10 and em-http-request 0.3.0.
# EM.error_handler catches the exception using em-http-request master.
#
# $ bundle exec thin start
# >> Using rack adapter
# >> Thin web server (v1.2.11 codename Bat-Shit Crazy)
# >> Maximum connections set to 1024
# >> Listening on 0.0.0.0:3000, CTRL+C to stop
# "yielding"
# "throwing"
# "resuming"
# /Users/Larry/Sites/pollex/config.ru:57:in `block (3 levels) in <main>': die (RuntimeError)
when '/http'
require 'em-http'
Fiber.new do
f = Fiber.current
http = EM::HttpRequest.new('http://getcloudapp.com').get
http.callback { p 'resuming'; f.resume(http) }
p 'yielding'
Fiber.yield
raise 'die'
end.resume
p 'throwing'
throw :async
###
# Crashes app server using eventmachine 0.12.10 and em-http-request 0.3.0.
# EM.error_handler catches the exception using em-http-request master.
#
# $ bundle exec thin start
# >> Using rack adapter
# >> Thin web server (v1.2.11 codename Bat-Shit Crazy)
# >> Maximum connections set to 1024
# >> Listening on 0.0.0.0:3000, CTRL+C to stop
# "throwing"
# "http.callback"
# /Users/Larry/Sites/pollex/config.ru:79:in `block (3 levels) in <main>': die (RuntimeError)
# from /Users/Larry/.rvm/gems/ruby-1.9.2-p180@pollex/gems/eventmachine-0.12.10/lib/em/deferrable.rb:134:in `call'
# from /Users/Larry/.rvm/gems/ruby-1.9.2-p180@pollex/gems/eventmachine-0.12.10/lib/em/deferrable.rb:134:in `set_deferred_status'
# from /Users/Larry/.rvm/gems/ruby-1.9.2-p180@pollex/gems/eventmachine-0.12.10/lib/em/deferrable.rb:173:in `succeed'
# from /Users/Larry/.rvm/gems/ruby-1.9.2-p180@pollex/gems/em-http-request-0.3.0/lib/em-http/client.rb:307:in `unbind'
# from /Users/Larry/.rvm/gems/ruby-1.9.2-p180@pollex/gems/eventmachine-0.12.10/lib/eventmachine.rb:1417:in `event_callback'
# from /Users/Larry/.rvm/gems/ruby-1.9.2-p180@pollex/gems/eventmachine-0.12.10/lib/eventmachine.rb:256:in `run_machine'
# from /Users/Larry/.rvm/gems/ruby-1.9.2-p180@pollex/gems/eventmachine-0.12.10/lib/eventmachine.rb:256:in `run'
# from /Users/Larry/.rvm/gems/ruby-1.9.2-p180@pollex/gems/thin-1.2.11/lib/thin/backends/base.rb:61:in `start'
# from /Users/Larry/.rvm/gems/ruby-1.9.2-p180@pollex/gems/thin-1.2.11/lib/thin/server.rb:159:in `start'
# from /Users/Larry/.rvm/gems/ruby-1.9.2-p180@pollex/gems/thin-1.2.11/lib/thin/controllers/controller.rb:86:in `start'
# from /Users/Larry/.rvm/gems/ruby-1.9.2-p180@pollex/gems/thin-1.2.11/lib/thin/runner.rb:185:in `run_command'
# from /Users/Larry/.rvm/gems/ruby-1.9.2-p180@pollex/gems/thin-1.2.11/lib/thin/runner.rb:151:in `run!'
# from /Users/Larry/.rvm/gems/ruby-1.9.2-p180@pollex/gems/thin-1.2.11/bin/thin:6:in `<top (required)>'
# from /Users/Larry/.rvm/gems/ruby-1.9.2-p180@pollex/bin/thin:19:in `load'
# from /Users/Larry/.rvm/gems/ruby-1.9.2-p180@pollex/bin/thin:19:in `<main>'
when '/http-no-fiber'
require 'em-http'
http = EM::HttpRequest.new('http://getcloudapp.com').get
p "EM.reactor_thread?: #{ EM.reactor_thread? }"
http.callback do
p 'http.callback'
p "EM.reactor_thread?: #{ EM.reactor_thread? }"
raise 'die'
end
p 'throwing'
throw :async
when '/defer'
operation = lambda { p 'operation' }
callback = lambda { |result| raise 'callback' }
EM.defer operation, callback
p 'throwing'
throw :async
###
# Caught by thin, maybe?
#
# $ bundle exec thin start
# >> Using rack adapter
# >> Thin web server (v1.2.11 codename Bat-Shit Crazy)
# >> Maximum connections set to 1024
# >> Listening on 0.0.0.0:3000, CTRL+C to stop
# !! Unexpected error while processing request: die
when '/die'
raise 'die'
###
# Crashes app server as expected.
#
# $ bundle exec thin start
# >> Using rack adapter
# >> Thin web server (v1.2.11 codename Bat-Shit Crazy)
# >> Maximum connections set to 1024
# >> Listening on 0.0.0.0:3000, CTRL+C to stop
# "throwing"
# /Users/Larry/Sites/pollex/config.ru:94:in `block (3 levels) in <main>': thread (RuntimeError)
when '/thread'
Thread.new do
sleep 1
raise 'thread'
end
p 'throwing'
throw :async
end
end)
source :gemcutter
gem 'em-http-request', :git => 'https://github.com/igrigorik/em-http-request.git'
gem 'thin'
GIT
remote: https://github.com/igrigorik/em-http-request.git
revision: ddfb713b29570d2f93713f619d94e5960ea8f627
specs:
em-http-request (1.0.0.beta.3)
addressable (>= 2.2.3)
em-socksify
eventmachine (>= 1.0.0.beta.3)
http_parser.rb (>= 0.5.1)
GEM
remote: http://rubygems.org/
specs:
addressable (2.2.6)
daemons (1.1.3)
em-socksify (0.1.0)
eventmachine
eventmachine (1.0.0.beta.3)
http_parser.rb (0.5.1)
rack (1.3.0)
thin (1.2.11)
daemons (>= 1.0.9)
eventmachine (>= 0.12.6)
rack (>= 1.0.0)
PLATFORMS
ruby
DEPENDENCIES
em-http-request!
thin
@lmarburger
Copy link
Author

I updated the gist to add a test case for raising an exception in a thread with Thread.abort_on_exception = true. The server dies in the same way as /http.

@lmarburger
Copy link
Author

Looks like it has nothing to do with fibers. I added /http-no-fiber that raises an exception in HttpClient#callback and it also takes down thin.

@igrigorik
Copy link

Larry, can you try building eventmachine from master? When I run your example, I get:

"throwing"
"http.callback"
"Thread.abort_on_exception: true"
"EM.error_handler: die"

As in, it doesn't blow up.

@lmarburger
Copy link
Author

Fantastic! Thin crashed out after only upgrading to eventmachine master but using it along with em-http-request master works like a champ.

@igrigorik
Copy link

Awesome. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment