diff options
author | Eric Wong <normalperson@yhbt.net> | 2009-11-18 17:28:12 -0800 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2009-11-18 17:40:46 -0800 |
commit | 15217fe1162a400fa1cd2216e395d9f17be8083e (patch) | |
tree | 657468e709e5438a82f4e93dcafc98fa01abc033 | |
parent | 57348bff1af3bd5817f1e7b12cd297d61d2f9414 (diff) | |
download | unicorn-15217fe1162a400fa1cd2216e395d9f17be8083e.tar.gz |
Shells already expand '~' before the executables see it, and relative paths inside symlinks can get set incorrectly to the actual directory name, and not the (usually desired) symlink name for things like Capistrano. Since our paths are now unexpanded, we must now check the "working_directory" directive and raise an error if the user specifies the config file in a way that makes the config file unreloadable.
-rwxr-xr-x | bin/unicorn | 4 | ||||
-rwxr-xr-x | bin/unicorn_rails | 2 | ||||
-rw-r--r-- | lib/unicorn/configurator.rb | 7 | ||||
-rw-r--r-- | test/exec/test_exec.rb | 51 |
4 files changed, 61 insertions, 3 deletions
diff --git a/bin/unicorn b/bin/unicorn index 225e819..325afb3 100755 --- a/bin/unicorn +++ b/bin/unicorn @@ -68,7 +68,7 @@ opts = OptionParser.new("", 24, ' ') do |opts| opts.on("-P", "--pid FILE", "DEPRECATED") do |f| warn %q{Use of --pid/-P is strongly discouraged} warn %q{Use the 'pid' directive in the Unicorn config file instead} - options[:pid] = File.expand_path(f) + options[:pid] = f end opts.on("-s", "--server SERVER", @@ -85,7 +85,7 @@ opts = OptionParser.new("", 24, ' ') do |opts| end opts.on("-c", "--config-file FILE", "Unicorn-specific config file") do |f| - options[:config_file] = File.expand_path(f) + options[:config_file] = f end # I'm avoiding Unicorn-specific config options on the command-line. diff --git a/bin/unicorn_rails b/bin/unicorn_rails index 36ed660..e46de70 100755 --- a/bin/unicorn_rails +++ b/bin/unicorn_rails @@ -75,7 +75,7 @@ opts = OptionParser.new("", 24, ' ') do |opts| end opts.on("-c", "--config-file FILE", "Unicorn-specific config file") do |f| - options[:config_file] = File.expand_path(f) + options[:config_file] = f end opts.on("-P PATH", "DEPRECATED") do |v| diff --git a/lib/unicorn/configurator.rb b/lib/unicorn/configurator.rb index 2d92aa3..e809b22 100644 --- a/lib/unicorn/configurator.rb +++ b/lib/unicorn/configurator.rb @@ -372,6 +372,13 @@ module Unicorn def working_directory(path) # just let chdir raise errors path = File.expand_path(path) + if config_file && + config_file[0] != ?/ && + ! test(?r, "#{path}/#{config_file}") + raise ArgumentError, + "config_file=#{config_file} would not be accessible in" \ + " working_directory=#{path}" + end Dir.chdir(path) HttpServer::START_CTX[:cwd] = ENV["PWD"] = path end diff --git a/test/exec/test_exec.rb b/test/exec/test_exec.rb index f6dfd6a..49762c0 100644 --- a/test/exec/test_exec.rb +++ b/test/exec/test_exec.rb @@ -82,6 +82,57 @@ end end end + def test_working_directory_rel_path_config_file + other = Tempfile.new('unicorn.wd') + File.unlink(other.path) + Dir.mkdir(other.path) + File.open("config.ru", "wb") do |fp| + fp.syswrite <<EOF +use Rack::ContentLength +run proc { |env| [ 200, { 'Content-Type' => 'text/plain' }, [ Dir.pwd ] ] } +EOF + end + FileUtils.cp("config.ru", other.path + "/config.ru") + Dir.chdir(@tmpdir) + + tmp = File.open('unicorn.config', 'wb') + tmp.syswrite <<EOF +working_directory '#@tmpdir' +listen '#@addr:#@port' +EOF + pid = xfork { redirect_test_io { exec($unicorn_bin, "-c#{tmp.path}") } } + wait_workers_ready("test_stderr.#{pid}.log", 1) + results = hit(["http://#@addr:#@port/"]) + assert_equal @tmpdir, results.first + File.truncate("test_stderr.#{pid}.log", 0) + + tmp.sysseek(0) + tmp.truncate(0) + tmp.syswrite <<EOF +working_directory '#{other.path}' +listen '#@addr:#@port' +EOF + + Process.kill(:HUP, pid) + lines = [] + re = /config_file=(.+) would not be accessible in working_directory=(.+)/ + until lines.grep(re) + sleep 0.1 + lines = File.readlines("test_stderr.#{pid}.log") + end + + File.truncate("test_stderr.#{pid}.log", 0) + FileUtils.cp('unicorn.config', other.path + "/unicorn.config") + Process.kill(:HUP, pid) + wait_workers_ready("test_stderr.#{pid}.log", 1) + results = hit(["http://#@addr:#@port/"]) + assert_equal other.path, results.first + + Process.kill(:QUIT, pid) + ensure + FileUtils.rmtree(other.path) + end + def test_working_directory other = Tempfile.new('unicorn.wd') File.unlink(other.path) |