Any signal other than -9 causes full CPU utilization by master unicorn process on FreeBSD

Mark Mccraw Mark.Mccraw at
Tue Jul 17 00:33:58 UTC 2012

Hi There!

I'm having a devil of a time figuring out a weird issue I'm running into.  I have unicorn configured to start 4 worker processes, and that works great.  However, when it's time to cycle the app, everything goes haywire. By trial and error, I have narrowed it down to this:  sending any signal to the master process other than SIGKILL fails miserably.  No new master process is created, as described in the documentation, nothing happens to the existing workers, nothing gets written to any log, and if I run top -u, I can see that very quickly the master ramps up to 100% CPU utilization.  This happens if I run 'kill -HUP <master pid>', 'kill -USR2 <master pid>', even 'kill -QUIT <master pid>'.

Here's what I'm running on:

uname -a
FreeBSD 9.0-RELEASE FreeBSD 9.0-RELEASE #0: Tue Jan  3 07:46:30 UTC 2012     root at  amd64

ruby -v
ruby 1.9.3p0 (2011-10-30 revision 33570) [amd64-freebsd9]

gem list | grep unicorn
unicorn (4.3.1)

My unicorn.rb file is pasted at the bottom.  It should be noted that I have tried every permutation of this I can think of to narrow out the problematic part (set preload_app to false, comment out preload_app), comment out before_exec, before_fork, after_fork, comment out the START_CTX[0] bit, etc), but things always fail the same way, so I'm guessing it's not the config, but I'm open to anything.  

Any suggestions at all are greatly appreciated.  I'd love to know how to interrupt the master process when it's slamming the CPU and get a stack trace, but I have no idea how in ruby.  Any thoughts?


working_directory APP_ROOT
pid "#{APP_ROOT}/tmp/pids/"
stderr_path "#{APP_ROOT}/log/unicorn.log"
stdout_path "#{APP_ROOT}/log/unicorn.log"
Unicorn::HttpServer::START_CTX[0] = "#{APP_ROOT}/bin/unicorn"
rails_env = ENV['RAILS_ENV'] || 'production'
worker_processes 4
timeout 120

# Speed up worker spawn times
preload_app true

listen "/tmp/unicorn.sock", :backlog => 10
listen "bb20web04:8080", :backlog => 1024

before_exec do |server|

before_fork do |server, worker|
  # When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
  # immediately start loading up a new version of itself (loaded with a new
  # version of our app). When this new Unicorn is completely loaded
  # it will begin spawning workers. The first worker spawned will check to
  # see if an .oldbin pidfile exists. If so, this means we've just booted up
  # a new Unicorn and need to tell the old one that it can now die. To do so
  # we send it a QUIT.
  # Using this method we get 0 downtime deploys.
  if defined?(ActiveRecord::Base)
  old_pid = APP_ROOT + '/tmp/pids/'
  if File.exists?(old_pid) && != old_pid
    rescue Errno::ENOENT, Errno::ESRCH
      # someone else did our job for us

after_fork do |server, worker|
  # Unicorn master loads the app then forks off workers - because of the way
  # Unix forking works, we need to make sure we aren't using any of the parent's
  # sockets, e.g. db connection
  if defined?(ActiveRecord::Base)
  # Redis and Memcached would go here but their connections are established
  # on demand, so the master never opens a socket

More information about the mongrel-unicorn mailing list