unicorn 0.91.0 → 0.92.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. data/{CHANGELOG → .CHANGELOG.old} +0 -0
  2. data/.document +4 -0
  3. data/.gitignore +5 -0
  4. data/.mailmap +26 -0
  5. data/CONTRIBUTORS +1 -1
  6. data/Documentation/.gitignore +5 -0
  7. data/Documentation/GNUmakefile +30 -0
  8. data/Documentation/unicorn.1.txt +158 -0
  9. data/Documentation/unicorn_rails.1.txt +150 -0
  10. data/GIT-VERSION-GEN +40 -0
  11. data/GNUmakefile +102 -14
  12. data/README +3 -2
  13. data/Rakefile +104 -32
  14. data/SIGNALS +2 -4
  15. data/TODO +3 -9
  16. data/bin/unicorn +5 -2
  17. data/bin/unicorn_rails +5 -3
  18. data/ext/unicorn_http/c_util.h +2 -2
  19. data/ext/unicorn_http/common_field_optimization.h +2 -1
  20. data/ext/unicorn_http/ext_help.h +29 -4
  21. data/ext/unicorn_http/extconf.rb +5 -0
  22. data/ext/unicorn_http/unicorn_http.rl +131 -76
  23. data/lib/unicorn.rb +6 -2
  24. data/lib/unicorn/app/exec_cgi.rb +3 -1
  25. data/lib/unicorn/app/inetd.rb +2 -0
  26. data/lib/unicorn/app/old_rails.rb +2 -0
  27. data/lib/unicorn/app/old_rails/static.rb +3 -1
  28. data/lib/unicorn/cgi_wrapper.rb +3 -1
  29. data/lib/unicorn/configurator.rb +2 -0
  30. data/lib/unicorn/const.rb +8 -6
  31. data/lib/unicorn/http_request.rb +6 -5
  32. data/lib/unicorn/http_response.rb +4 -2
  33. data/lib/unicorn/launcher.rb +6 -0
  34. data/lib/unicorn/socket_helper.rb +5 -5
  35. data/lib/unicorn/tee_input.rb +2 -0
  36. data/lib/unicorn/util.rb +2 -0
  37. data/local.mk.sample +4 -2
  38. data/setup.rb +1 -0
  39. data/test/aggregate.rb +2 -0
  40. data/test/exec/test_exec.rb +157 -0
  41. data/test/rails/app-1.2.3/app/controllers/application.rb +2 -0
  42. data/test/rails/app-1.2.3/app/controllers/foo_controller.rb +2 -0
  43. data/test/rails/app-1.2.3/app/helpers/application_helper.rb +2 -0
  44. data/test/rails/app-1.2.3/config/boot.rb +2 -0
  45. data/test/rails/app-1.2.3/config/environment.rb +2 -0
  46. data/test/rails/app-1.2.3/config/environments/development.rb +2 -0
  47. data/test/rails/app-1.2.3/config/environments/production.rb +2 -0
  48. data/test/rails/app-1.2.3/config/routes.rb +2 -0
  49. data/test/rails/app-2.0.2/app/controllers/application.rb +2 -0
  50. data/test/rails/app-2.0.2/app/controllers/foo_controller.rb +2 -0
  51. data/test/rails/app-2.0.2/app/helpers/application_helper.rb +2 -0
  52. data/test/rails/app-2.0.2/config/boot.rb +2 -0
  53. data/test/rails/app-2.0.2/config/environment.rb +2 -0
  54. data/test/rails/app-2.0.2/config/environments/development.rb +2 -0
  55. data/test/rails/app-2.0.2/config/environments/production.rb +2 -0
  56. data/test/rails/app-2.0.2/config/routes.rb +2 -0
  57. data/test/rails/app-2.1.2/app/controllers/application.rb +2 -0
  58. data/test/rails/app-2.1.2/app/controllers/foo_controller.rb +2 -0
  59. data/test/rails/app-2.1.2/app/helpers/application_helper.rb +2 -0
  60. data/test/rails/app-2.1.2/config/boot.rb +2 -0
  61. data/test/rails/app-2.1.2/config/environment.rb +2 -0
  62. data/test/rails/app-2.1.2/config/environments/development.rb +2 -0
  63. data/test/rails/app-2.1.2/config/environments/production.rb +2 -0
  64. data/test/rails/app-2.1.2/config/routes.rb +2 -0
  65. data/test/rails/app-2.2.2/app/controllers/application.rb +2 -0
  66. data/test/rails/app-2.2.2/app/controllers/foo_controller.rb +2 -0
  67. data/test/rails/app-2.2.2/app/helpers/application_helper.rb +2 -0
  68. data/test/rails/app-2.2.2/config/boot.rb +2 -0
  69. data/test/rails/app-2.2.2/config/environment.rb +2 -0
  70. data/test/rails/app-2.2.2/config/environments/development.rb +2 -0
  71. data/test/rails/app-2.2.2/config/environments/production.rb +2 -0
  72. data/test/rails/app-2.2.2/config/routes.rb +2 -0
  73. data/test/rails/app-2.3.3.1/app/controllers/application_controller.rb +2 -0
  74. data/test/rails/app-2.3.3.1/app/controllers/foo_controller.rb +2 -0
  75. data/test/rails/app-2.3.3.1/app/helpers/application_helper.rb +2 -0
  76. data/test/rails/app-2.3.3.1/config/boot.rb +2 -0
  77. data/test/rails/app-2.3.3.1/config/environment.rb +2 -0
  78. data/test/rails/app-2.3.3.1/config/environments/development.rb +2 -0
  79. data/test/rails/app-2.3.3.1/config/environments/production.rb +2 -0
  80. data/test/rails/app-2.3.3.1/config/routes.rb +2 -0
  81. data/test/rails/test_rails.rb +2 -0
  82. data/test/test_helper.rb +8 -0
  83. data/test/unit/test_configurator.rb +2 -0
  84. data/test/unit/test_http_parser.rb +13 -0
  85. data/test/unit/test_http_parser_ng.rb +2 -0
  86. data/test/unit/test_request.rb +2 -0
  87. data/test/unit/test_response.rb +2 -0
  88. data/test/unit/test_server.rb +2 -0
  89. data/test/unit/test_signals.rb +2 -0
  90. data/test/unit/test_socket_helper.rb +2 -0
  91. data/test/unit/test_tee_input.rb +2 -1
  92. data/test/unit/test_upload.rb +2 -0
  93. data/test/unit/test_util.rb +2 -0
  94. data/unicorn.gemspec +38 -28
  95. metadata +38 -42
  96. data/Manifest +0 -137
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  require 'unicorn'
2
4
 
3
5
  module Unicorn::App
@@ -24,7 +26,7 @@ module Unicorn::App
24
26
  SERVER_PORT
25
27
  SERVER_PROTOCOL
26
28
  SERVER_SOFTWARE
27
- ).map { |x| x.freeze }.freeze # frozen strings are faster for Hash lookups
29
+ ).map { |x| x.freeze } # frozen strings are faster for Hash assignments
28
30
 
29
31
  # Intializes the app, example of usage in a config.ru
30
32
  # map "/cgit" do
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  # Copyright (c) 2009 Eric Wong
2
4
  # You can redistribute it and/or modify it under the same terms as Ruby.
3
5
 
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  # This code is based on the original Rails handler in Mongrel
2
4
  # Copyright (c) 2005 Zed A. Shaw
3
5
  # Copyright (c) 2009 Eric Wong
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  # This code is based on the original Rails handler in Mongrel
2
4
  # Copyright (c) 2005 Zed A. Shaw
3
5
  # Copyright (c) 2009 Eric Wong
@@ -18,7 +20,7 @@
18
20
  # with Unicorn and you should see a decent speed boost (but not as
19
21
  # fast as if you use a static server like nginx).
20
22
  class Unicorn::App::OldRails::Static < Struct.new(:app, :root, :file_server)
21
- FILE_METHODS = { 'GET' => true, 'HEAD' => true }.freeze
23
+ FILE_METHODS = { 'GET' => true, 'HEAD' => true }
22
24
  REQUEST_METHOD = 'REQUEST_METHOD'.freeze
23
25
  REQUEST_URI = 'REQUEST_URI'.freeze
24
26
  PATH_INFO = 'PATH_INFO'.freeze
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  # This code is based on the original CGIWrapper from Mongrel
2
4
  # Copyright (c) 2005 Zed A. Shaw
3
5
  # Copyright (c) 2009 Eric Wong
@@ -44,7 +46,7 @@ class Unicorn::CGIWrapper < ::CGI
44
46
  'language' => 'Content-Language'.freeze,
45
47
  'expires' => 'Expires'.freeze,
46
48
  'length' => CONTENT_LENGTH,
47
- }.freeze
49
+ }
48
50
 
49
51
  # Takes an a Rackable environment, plus any additional CGI.new
50
52
  # arguments These are used internally to create a wrapper around the
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  require 'socket'
2
4
  require 'logger'
3
5
 
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  module Unicorn
2
4
 
3
5
  # Frequently used constants when constructing requests or responses. Many times
@@ -5,11 +7,11 @@ module Unicorn
5
7
  # gave about a 3% to 10% performance improvement over using the strings directly.
6
8
  # Symbols did not really improve things much compared to constants.
7
9
  module Const
8
- UNICORN_VERSION="0.91.0".freeze
10
+ UNICORN_VERSION="0.92.0"
9
11
 
10
- DEFAULT_HOST = "0.0.0.0".freeze # default TCP listen host address
11
- DEFAULT_PORT = "8080".freeze # default TCP listen port
12
- DEFAULT_LISTEN = "#{DEFAULT_HOST}:#{DEFAULT_PORT}".freeze
12
+ DEFAULT_HOST = "0.0.0.0" # default TCP listen host address
13
+ DEFAULT_PORT = "8080" # default TCP listen port
14
+ DEFAULT_LISTEN = "#{DEFAULT_HOST}:#{DEFAULT_PORT}"
13
15
 
14
16
  # The basic max request size we'll try to read.
15
17
  CHUNK_SIZE=(16 * 1024)
@@ -22,8 +24,8 @@ module Unicorn
22
24
  MAX_BODY=MAX_HEADER
23
25
 
24
26
  # common errors we'll send back
25
- ERROR_400_RESPONSE = "HTTP/1.1 400 Bad Request\r\n\r\n".freeze
26
- ERROR_500_RESPONSE = "HTTP/1.1 500 Internal Server Error\r\n\r\n".freeze
27
+ ERROR_400_RESPONSE = "HTTP/1.1 400 Bad Request\r\n\r\n"
28
+ ERROR_500_RESPONSE = "HTTP/1.1 500 Internal Server Error\r\n\r\n"
27
29
  EXPECT_100_RESPONSE = "HTTP/1.1 100 Continue\r\n\r\n"
28
30
 
29
31
  # A frozen format for this is about 15% faster
@@ -1,4 +1,5 @@
1
- # coding:binary
1
+ # -*- encoding: binary -*-
2
+
2
3
  require 'stringio'
3
4
  require 'unicorn_http'
4
5
 
@@ -11,15 +12,15 @@ module Unicorn
11
12
  "rack.multiprocess" => true,
12
13
  "rack.multithread" => false,
13
14
  "rack.run_once" => false,
14
- "rack.version" => [1, 0].freeze,
15
- "SCRIPT_NAME" => "".freeze,
15
+ "rack.version" => [1, 0],
16
+ "SCRIPT_NAME" => "",
16
17
 
17
18
  # this is not in the Rack spec, but some apps may rely on it
18
- "SERVER_SOFTWARE" => "Unicorn #{Const::UNICORN_VERSION}".freeze
19
+ "SERVER_SOFTWARE" => "Unicorn #{Const::UNICORN_VERSION}"
19
20
  }
20
21
 
21
22
  NULL_IO = StringIO.new(Z)
22
- LOCALHOST = '127.0.0.1'.freeze
23
+ LOCALHOST = '127.0.0.1'
23
24
 
24
25
  # Being explicitly single-threaded, we have certain advantages in
25
26
  # not having to worry about variables being clobbered :)
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  require 'time'
2
4
 
3
5
  module Unicorn
@@ -30,7 +32,7 @@ module Unicorn
30
32
  # Rack does not set/require a Date: header. We always override the
31
33
  # Connection: and Date: headers no matter what (if anything) our
32
34
  # Rack application sent us.
33
- SKIP = { 'connection' => true, 'date' => true, 'status' => true }.freeze
35
+ SKIP = { 'connection' => true, 'date' => true, 'status' => true }
34
36
  OUT = [] # :nodoc
35
37
 
36
38
  def self.write_header(socket, status, headers)
@@ -67,7 +69,7 @@ module Unicorn
67
69
  body.each { |chunk| socket.write(chunk) }
68
70
  socket.close # flushes and uncorks the socket immediately
69
71
  ensure
70
- body.respond_to?(:close) and body.close rescue nil
72
+ body.respond_to?(:close) and body.close
71
73
  end
72
74
 
73
75
  end
@@ -1,4 +1,10 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  $stdin.sync = $stdout.sync = $stderr.sync = true
4
+ $stdin.binmode
5
+ $stdout.binmode
6
+ $stderr.binmode
7
+
2
8
  require 'unicorn'
3
9
 
4
10
  class Unicorn::Launcher
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  require 'socket'
2
4
 
3
5
  module Unicorn
@@ -18,10 +20,8 @@ module Unicorn
18
20
  # Use the HTTP accept filter if available.
19
21
  # The struct made by pack() is defined in /usr/include/sys/socket.h
20
22
  # as accept_filter_arg
21
- # We won't be seupportin the "dataready" filter unlike nginx
22
- # since we only support HTTP and no other protocols
23
23
  unless `/sbin/sysctl -nq net.inet.accf.http`.empty?
24
- HTTPREADY = ['httpready', nil].pack('a16a240').freeze
24
+ FILTER_ARG = ['httpready', nil].pack('a16a240')
25
25
  end
26
26
  end
27
27
 
@@ -44,8 +44,8 @@ module Unicorn
44
44
  # No good reason to ever have deferred accepts off
45
45
  if defined?(TCP_DEFER_ACCEPT)
46
46
  sock.setsockopt(SOL_TCP, TCP_DEFER_ACCEPT, 1) rescue nil
47
- elsif defined?(SO_ACCEPTFILTER) && defined?(HTTPREADY)
48
- sock.setsockopt(SOL_SOCKET, SO_ACCEPTFILTER, HTTPREADY) rescue nil
47
+ elsif defined?(SO_ACCEPTFILTER) && defined?(FILTER_ARG)
48
+ sock.setsockopt(SOL_SOCKET, SO_ACCEPTFILTER, FILTER_ARG) rescue nil
49
49
  end
50
50
  end
51
51
 
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  module Unicorn
2
4
 
3
5
  # acts like tee(1) on an input input to provide a input-like stream
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  require 'fcntl'
2
4
  require 'tmpdir'
3
5
 
@@ -31,6 +31,7 @@ test-19:
31
31
  publish_doc:
32
32
  -git set-file-times
33
33
  $(MAKE) doc
34
+ awk 'BEGIN{RS="=== ";ORS=""}NR==2{ print RS""$$0 }' NEWS > doc/LATEST
34
35
  $(MAKE) doc_gz
35
36
  rsync -av --delete doc/ dcvr:/srv/unicorn/
36
37
  git ls-files | xargs touch
@@ -38,7 +39,8 @@ publish_doc:
38
39
  # Create gzip variants of the same timestamp as the original so nginx
39
40
  # "gzip_static on" can serve the gzipped versions directly.
40
41
  doc_gz: suf := html js css
41
- doc_gz: docs = $(shell find doc/ -regex '^.*\.\(html\|js\|css\)$$') doc/COPYING
42
+ doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
42
43
  doc_gz:
44
+ touch doc/NEWS.atom.xml -d "$$(awk 'NR==1{print $$4,$$5,$$6}' NEWS)"
43
45
  for i in $(docs); do \
44
- gzip --rsyncable < $$i > $$i.gz; touch -r $$i $$i.gz; done
46
+ gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
data/setup.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- encoding: binary -*-
1
2
  #
2
3
  # setup.rb
3
4
  #
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/ruby -n
2
+ # -*- encoding: binary -*-
3
+
2
4
  BEGIN { $tests = $assertions = $failures = $errors = 0 }
3
5
 
4
6
  $_ =~ /(\d+) tests, (\d+) assertions, (\d+) failures, (\d+) errors/ or next
@@ -1,4 +1,7 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  # Copyright (c) 2009 Eric Wong
4
+ FLOCK_PATH = File.expand_path(__FILE__)
2
5
  require 'test/test_helper'
3
6
 
4
7
  do_test = true
@@ -695,4 +698,158 @@ end
695
698
  wait_for_death(pid)
696
699
  end
697
700
 
701
+ def hup_test_common(preload)
702
+ File.open("config.ru", "wb") { |fp| fp.syswrite(HI.gsub("HI", '#$$')) }
703
+ pid_file = Tempfile.new('pid')
704
+ ucfg = Tempfile.new('unicorn_test_config')
705
+ ucfg.syswrite("listen '#@addr:#@port'\n")
706
+ ucfg.syswrite("pid '#{pid_file.path}'\n")
707
+ ucfg.syswrite("preload_app true\n") if preload
708
+ ucfg.syswrite("stderr_path 'test_stderr.#$$.log'\n")
709
+ ucfg.syswrite("stdout_path 'test_stdout.#$$.log'\n")
710
+ pid = xfork {
711
+ redirect_test_io { exec($unicorn_bin, "-D", "-c", ucfg.path) }
712
+ }
713
+ _, status = Process.waitpid2(pid)
714
+ assert status.success?
715
+ wait_master_ready("test_stderr.#$$.log")
716
+ wait_workers_ready("test_stderr.#$$.log", 1)
717
+ uri = URI.parse("http://#@addr:#@port/")
718
+ pids = Tempfile.new('worker_pids')
719
+ hitter = fork {
720
+ bodies = Hash.new(0)
721
+ at_exit { pids.syswrite(bodies.inspect) }
722
+ trap(:TERM) { exit(0) }
723
+ loop {
724
+ rv = Net::HTTP.get(uri)
725
+ pid = rv.to_i
726
+ exit!(1) if pid <= 0
727
+ bodies[pid] += 1
728
+ }
729
+ }
730
+ sleep 1 # racy
731
+ daemon_pid = pid_file.read.to_i
732
+ assert daemon_pid > 0
733
+ Process.kill(:HUP, daemon_pid)
734
+ sleep 1 # racy
735
+ assert_nothing_raised { Process.kill(:TERM, hitter) }
736
+ _, hitter_status = Process.waitpid2(hitter)
737
+ assert hitter_status.success?
738
+ pids.sysseek(0)
739
+ pids = eval(pids.read)
740
+ assert_kind_of(Hash, pids)
741
+ assert_equal 2, pids.size
742
+ pids.keys.each { |x|
743
+ assert_kind_of(Integer, x)
744
+ assert x > 0
745
+ assert pids[x] > 0
746
+ }
747
+ assert_nothing_raised { Process.kill(:QUIT, daemon_pid) }
748
+ wait_for_death(daemon_pid)
749
+ end
750
+
751
+ def test_preload_app_hup
752
+ hup_test_common(true)
753
+ end
754
+
755
+ def test_hup
756
+ hup_test_common(false)
757
+ end
758
+
759
+ def test_default_listen_hup_holds_listener
760
+ default_listen_lock do
761
+ res, pid_path = default_listen_setup
762
+ daemon_pid = File.read(pid_path).to_i
763
+ assert_nothing_raised { Process.kill(:HUP, daemon_pid) }
764
+ wait_workers_ready("test_stderr.#$$.log", 1)
765
+ res2 = hit(["http://#{Unicorn::Const::DEFAULT_LISTEN}/"])
766
+ assert_match %r{\d+}, res2.first
767
+ assert res2.first != res.first
768
+ assert_nothing_raised { Process.kill(:QUIT, daemon_pid) }
769
+ wait_for_death(daemon_pid)
770
+ end
771
+ end
772
+
773
+ def test_default_listen_upgrade_holds_listener
774
+ default_listen_lock do
775
+ res, pid_path = default_listen_setup
776
+ daemon_pid = File.read(pid_path).to_i
777
+ assert_nothing_raised {
778
+ Process.kill(:USR2, daemon_pid)
779
+ wait_for_file("#{pid_path}.oldbin")
780
+ wait_for_file(pid_path)
781
+ Process.kill(:QUIT, daemon_pid)
782
+ wait_for_death(daemon_pid)
783
+ }
784
+ daemon_pid = File.read(pid_path).to_i
785
+ wait_workers_ready("test_stderr.#$$.log", 1)
786
+ File.truncate("test_stderr.#$$.log", 0)
787
+
788
+ res2 = hit(["http://#{Unicorn::Const::DEFAULT_LISTEN}/"])
789
+ assert_match %r{\d+}, res2.first
790
+ assert res2.first != res.first
791
+
792
+ assert_nothing_raised { Process.kill(:HUP, daemon_pid) }
793
+ wait_workers_ready("test_stderr.#$$.log", 1)
794
+ File.truncate("test_stderr.#$$.log", 0)
795
+ res3 = hit(["http://#{Unicorn::Const::DEFAULT_LISTEN}/"])
796
+ assert res2.first != res3.first
797
+
798
+ assert_nothing_raised { Process.kill(:QUIT, daemon_pid) }
799
+ wait_for_death(daemon_pid)
800
+ end
801
+ end
802
+
803
+ def default_listen_setup
804
+ File.open("config.ru", "wb") { |fp| fp.syswrite(HI.gsub("HI", '#$$')) }
805
+ pid_path = (tmp = Tempfile.new('pid')).path
806
+ tmp.close!
807
+ ucfg = Tempfile.new('unicorn_test_config')
808
+ ucfg.syswrite("pid '#{pid_path}'\n")
809
+ ucfg.syswrite("stderr_path 'test_stderr.#$$.log'\n")
810
+ ucfg.syswrite("stdout_path 'test_stdout.#$$.log'\n")
811
+ pid = xfork {
812
+ redirect_test_io { exec($unicorn_bin, "-D", "-c", ucfg.path) }
813
+ }
814
+ _, status = Process.waitpid2(pid)
815
+ assert status.success?
816
+ wait_master_ready("test_stderr.#$$.log")
817
+ wait_workers_ready("test_stderr.#$$.log", 1)
818
+ File.truncate("test_stderr.#$$.log", 0)
819
+ res = hit(["http://#{Unicorn::Const::DEFAULT_LISTEN}/"])
820
+ assert_match %r{\d+}, res.first
821
+ [ res, pid_path ]
822
+ end
823
+
824
+ # we need to flock() something to prevent these tests from running
825
+ def default_listen_lock(&block)
826
+ fp = File.open(FLOCK_PATH, "rb")
827
+ begin
828
+ fp.flock(File::LOCK_EX)
829
+ begin
830
+ TCPServer.new(Unicorn::Const::DEFAULT_HOST,
831
+ Unicorn::Const::DEFAULT_PORT).close
832
+ rescue Errno::EADDRINUSE, Errno::EACCES
833
+ warn "can't bind to #{Unicorn::Const::DEFAULT_LISTEN}"
834
+ return false
835
+ end
836
+
837
+ # unused_port should never take this, but we may run an environment
838
+ # where tests are being run against older unicorns...
839
+ lock_path = "#{Dir::tmpdir}/unicorn_test." \
840
+ "#{Unicorn::Const::DEFAULT_LISTEN}.lock"
841
+ begin
842
+ lock = File.open(lock_path, File::WRONLY|File::CREAT|File::EXCL, 0600)
843
+ yield
844
+ rescue Errno::EEXIST
845
+ lock_path = nil
846
+ return false
847
+ ensure
848
+ File.unlink(lock_path) if lock_path
849
+ end
850
+ ensure
851
+ fp.flock(File::LOCK_UN)
852
+ end
853
+ end
854
+
698
855
  end if do_test
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  class ApplicationController < ActionController::Base
2
4
  # Pick a unique cookie name to distinguish our session data from others'
3
5
  session :session_key => "_unicorn_rails_test.#{rand}"
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  require 'digest/sha1'
2
4
  class FooController < ApplicationController
3
5
  def index
@@ -1,2 +1,4 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  module ApplicationHelper
2
4
  end
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  unless defined?(RAILS_ROOT)
2
4
  root_path = File.join(File.dirname(__FILE__), '..')
3
5
  RAILS_ROOT = root_path
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  unless defined? RAILS_GEM_VERSION
2
4
  RAILS_GEM_VERSION = ENV['UNICORN_RAILS_VERSION'] # || '1.2.3'
3
5
  end
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  config.cache_classes = false
2
4
  config.whiny_nils = true
3
5
  config.breakpoint_server = true
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+
1
3
  config.cache_classes = true
2
4
  config.action_controller.consider_all_requests_local = false
3
5
  config.action_controller.perform_caching = true