about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-03-18 01:59:17 -0700
committerEric Wong <normalperson@yhbt.net>2009-03-18 14:30:46 -0700
commit29c6af908c2bd1109be175c34b89c45c8cc2f60b (patch)
tree076b9cf2a415504001f2aa63af1cc74bfd02052e
parent2373b663049df69a168f1e876e817a49d8ed8a7b (diff)
downloadunicorn-29c6af908c2bd1109be175c34b89c45c8cc2f60b.tar.gz
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).
-rw-r--r--SIGNALS2
-rw-r--r--lib/unicorn.rb10
-rw-r--r--lib/unicorn/configurator.rb4
3 files changed, 15 insertions, 1 deletions
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