Skip to content

Instantly share code, notes, and snippets.

@tdl
Last active January 18, 2021 07:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tdl/5564904 to your computer and use it in GitHub Desktop.
Save tdl/5564904 to your computer and use it in GitHub Desktop.
Hacky Rack middleware to get backtrace of hung Unicorn workers
# config/application.rb
require File.expand_path('../boot', __FILE__)
require 'rails/all'
Bundler.require(:default, Rails.env)
module MyApp
class Application < Rails::Application
# configure Rails to inject this middleware. Must be at least after Rails logger!
require File.expand_path('../../lib/log_before_timeout', __FILE__)
config.middleware.use LogBeforeTimeout
# to insert at start of chain instead:
# config.middleware.insert(0, LogBeforeTimeout)
# to insert before a specific middleware
#config.middleware.insert_before(ActionDispatch::Static, LogBeforeTimeout)
end
end
# lib/log_before_timeout.rb
class LogBeforeTimeout < Struct.new(:app)
def call(env)
thr = Thread.new(Thread.current) do |request_thread|
sleep(14) # set this to Unicorn timeout - 1
unless Thread.current[:done]
# instead of Rails.logger you should be able to use env["rack.logger"],
# but I never got this to work (was always nil in my Rails app)
Rails.logger.warn "about to die from SIGKILL. thread:"
Rails.logger.warn "#{request_thread.inspect}"
Rails.logger.warn request_thread.backtrace.join("\n").prepend("\n")
end
end
app.call(env)
ensure
thr[:done] = true
thr.run
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment