From 29c6af908c2bd1109be175c34b89c45c8cc2f60b Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 18 Mar 2009 01:59:17 -0700 Subject: gracefully die if working dir is invalid at fork In nearly every app, if the current working directory disappears, the app becomes broken, sometimes subtly. It can be especially broken when preload_app is false (the default). So just shut ourselves down to spare ourselves the wasted CPU cycles on a dead app. As a (hopefully) pleasant side effect, this allows configurations with preload_app==false (the default) to do application code reloads via SIGHUP (in addition to unicorn config reloads). --- SIGNALS | 2 ++ lib/unicorn.rb | 10 +++++++++- lib/unicorn/configurator.rb | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/SIGNALS b/SIGNALS index 40f9c3d..c7c3833 100644 --- a/SIGNALS +++ b/SIGNALS @@ -7,6 +7,8 @@ processes are documented here as well. === Master Process * HUP - reload config file and gracefully restart all workers + If preload_app is false (the default), the application code + will be reloaded when workers are restarted as well. * INT/TERM - quick shutdown, kills all workers immediately diff --git a/lib/unicorn.rb b/lib/unicorn.rb index d442f63..4f7d417 100644 --- a/lib/unicorn.rb +++ b/lib/unicorn.rb @@ -53,6 +53,7 @@ module Unicorn @start_ctx = DEFAULT_START_CTX.dup @start_ctx.merge!(start_ctx) if start_ctx @app = app + @alive = true @mode = :idle @master_pid = $$ @workers = Hash.new @@ -165,7 +166,7 @@ module Unicorn $0 = "unicorn master" logger.info "master process ready" # test relies on this message begin - loop do + while @alive reap_all_workers case @mode when :idle @@ -352,6 +353,13 @@ module Unicorn return if @workers.size == @worker_processes (0...@worker_processes).each do |worker_nr| @workers.values.include?(worker_nr) and next + begin + Dir.chdir(@start_ctx[:cwd]) + rescue Errno::ENOENT => err + logger.fatal "#{err.inspect} (#{@start_ctx[:cwd]})" + @alive = false + return + end tempfile = Tempfile.new('') # as short as possible to save dir space tempfile.unlink # don't allow other processes to find or see it tempfile.sync = true diff --git a/lib/unicorn/configurator.rb b/lib/unicorn/configurator.rb index dd9ae3b..ae74c2b 100644 --- a/lib/unicorn/configurator.rb +++ b/lib/unicorn/configurator.rb @@ -194,6 +194,10 @@ module Unicorn # properly close/reopen sockets. Files opened for logging do not # have to be reopened as (unbuffered-in-userspace) files opened with # the File::APPEND flag are written to atomically on UNIX. + # + # In addition to reloading the unicorn-specific config settings, + # SIGHUP will reload application code in the working + # directory/symlink when workers are gracefully restarted. def preload_app(bool) case bool when TrueClass, FalseClass -- cgit v1.2.3-24-ge0c7