Skip to content

Instantly share code, notes, and snippets.

@sonots
Last active April 3, 2016 06:56
Show Gist options
  • Save sonots/1d1a2fd21b0f6df1d4cb to your computer and use it in GitHub Desktop.
Save sonots/1d1a2fd21b0f6df1d4cb to your computer and use it in GitHub Desktop.
Gracefully restart unicorn using Server::Starter
start_server --status-file=/path/to/app/log/start_server.stat \
--port=10080 --signal-on-hup=CONT --dir=/path/to/app -- \
bundle exec --keep-file-descriptors unicorn -c config/unicorn.conf.rb config.ru
worker_processes 4
preload_app true
APP_ROOT = File.expand_path('../..', __FILE__)
status_file = File.join(APP_ROOT, 'log/start_server.stat')
if ENV.key?('SERVER_STARTER_PORT')
fds = ENV['SERVER_STARTER_PORT'].split(';').map { |x|
path_or_port, fd = x.split('=', 2)
fd
}
ENV['UNICORN_FD'] = fds.join(',')
ENV.delete('SERVER_STARTER_PORT')
else
listen ENV['PORT'] || '10080'
end
before_fork do |server, worker|
defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
# Throttle the master from forking too quickly by sleeping. Due
# to the implementation of standard Unix signal handlers, this
# helps (but does not completely) prevent identical, repeated signals
# from being lost when the receiving process is busy.
sleep 1
end
after_fork do |server, worker|
defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
begin
# This allows a new master process to incrementally
# phase out the old master process with SIGTTOU to avoid a
# thundering herd (especially in the "preload_app false" case)
# when doing a transparent upgrade. The last worker spawned
# will then kill off the old master process with a SIGQUIT.
pids = File.readlines(status_file).map {|_| _.chomp.split(':') }.to_h
old_gen = ENV['SERVER_STARTER_GENERATION'].to_i - 1
if old_pid = pids[old_gen.to_s]
sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
Process.kill(sig, old_pid.to_i)
end
rescue Errno::ENOENT, Errno::ESRCH => e
$stderr.puts "#{e.class} #{e.message}"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment