boourns-unicorn 4.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. data/.CHANGELOG.old +25 -0
  2. data/.document +29 -0
  3. data/.gitignore +24 -0
  4. data/.mailmap +26 -0
  5. data/.wrongdoc.yml +10 -0
  6. data/Application_Timeouts +77 -0
  7. data/CONTRIBUTORS +35 -0
  8. data/COPYING +674 -0
  9. data/DESIGN +97 -0
  10. data/Documentation/.gitignore +5 -0
  11. data/Documentation/GNUmakefile +30 -0
  12. data/Documentation/unicorn.1.txt +174 -0
  13. data/Documentation/unicorn_rails.1.txt +175 -0
  14. data/FAQ +53 -0
  15. data/GIT-VERSION-GEN +40 -0
  16. data/GNUmakefile +267 -0
  17. data/HACKING +134 -0
  18. data/ISSUES +36 -0
  19. data/KNOWN_ISSUES +79 -0
  20. data/LICENSE +64 -0
  21. data/Links +56 -0
  22. data/PHILOSOPHY +145 -0
  23. data/README +149 -0
  24. data/Rakefile +97 -0
  25. data/SIGNALS +114 -0
  26. data/Sandbox +96 -0
  27. data/TODO +5 -0
  28. data/TUNING +98 -0
  29. data/bin/unicorn +121 -0
  30. data/bin/unicorn_rails +209 -0
  31. data/examples/big_app_gc.rb +2 -0
  32. data/examples/echo.ru +27 -0
  33. data/examples/git.ru +13 -0
  34. data/examples/init.sh +74 -0
  35. data/examples/logger_mp_safe.rb +25 -0
  36. data/examples/logrotate.conf +29 -0
  37. data/examples/nginx.conf +156 -0
  38. data/examples/unicorn.conf.minimal.rb +13 -0
  39. data/examples/unicorn.conf.rb +94 -0
  40. data/ext/unicorn_http/CFLAGS +13 -0
  41. data/ext/unicorn_http/c_util.h +124 -0
  42. data/ext/unicorn_http/common_field_optimization.h +111 -0
  43. data/ext/unicorn_http/ext_help.h +86 -0
  44. data/ext/unicorn_http/extconf.rb +10 -0
  45. data/ext/unicorn_http/global_variables.h +97 -0
  46. data/ext/unicorn_http/httpdate.c +82 -0
  47. data/ext/unicorn_http/unicorn_http.rl +1036 -0
  48. data/ext/unicorn_http/unicorn_http_common.rl +76 -0
  49. data/lib/unicorn.rb +107 -0
  50. data/lib/unicorn/app/exec_cgi.rb +154 -0
  51. data/lib/unicorn/app/inetd.rb +109 -0
  52. data/lib/unicorn/app/old_rails.rb +35 -0
  53. data/lib/unicorn/app/old_rails/static.rb +59 -0
  54. data/lib/unicorn/cgi_wrapper.rb +147 -0
  55. data/lib/unicorn/configurator.rb +630 -0
  56. data/lib/unicorn/const.rb +40 -0
  57. data/lib/unicorn/http_request.rb +83 -0
  58. data/lib/unicorn/http_response.rb +45 -0
  59. data/lib/unicorn/http_server.rb +755 -0
  60. data/lib/unicorn/launcher.rb +62 -0
  61. data/lib/unicorn/oob_gc.rb +71 -0
  62. data/lib/unicorn/preread_input.rb +33 -0
  63. data/lib/unicorn/socket_helper.rb +208 -0
  64. data/lib/unicorn/ssl_client.rb +11 -0
  65. data/lib/unicorn/ssl_configurator.rb +104 -0
  66. data/lib/unicorn/ssl_server.rb +42 -0
  67. data/lib/unicorn/stream_input.rb +149 -0
  68. data/lib/unicorn/tee_input.rb +126 -0
  69. data/lib/unicorn/tmpio.rb +29 -0
  70. data/lib/unicorn/util.rb +69 -0
  71. data/lib/unicorn/worker.rb +88 -0
  72. data/local.mk.sample +59 -0
  73. data/script/isolate_for_tests +32 -0
  74. data/setup.rb +1586 -0
  75. data/t/.gitignore +5 -0
  76. data/t/GNUmakefile +82 -0
  77. data/t/README +42 -0
  78. data/t/bin/content-md5-put +36 -0
  79. data/t/bin/sha1sum.rb +17 -0
  80. data/t/bin/unused_listen +40 -0
  81. data/t/bin/utee +12 -0
  82. data/t/broken-app.ru +12 -0
  83. data/t/detach.ru +11 -0
  84. data/t/env.ru +3 -0
  85. data/t/heartbeat-timeout.ru +12 -0
  86. data/t/listener_names.ru +4 -0
  87. data/t/my-tap-lib.sh +201 -0
  88. data/t/oob_gc.ru +21 -0
  89. data/t/oob_gc_path.ru +21 -0
  90. data/t/pid.ru +3 -0
  91. data/t/preread_input.ru +17 -0
  92. data/t/rack-input-tests.ru +21 -0
  93. data/t/sslgen.sh +71 -0
  94. data/t/t0000-http-basic.sh +50 -0
  95. data/t/t0001-reload-bad-config.sh +53 -0
  96. data/t/t0002-config-conflict.sh +49 -0
  97. data/t/t0002-parser-error.sh +94 -0
  98. data/t/t0003-working_directory.sh +51 -0
  99. data/t/t0004-heartbeat-timeout.sh +69 -0
  100. data/t/t0004-working_directory_broken.sh +24 -0
  101. data/t/t0005-working_directory_app.rb.sh +37 -0
  102. data/t/t0006-reopen-logs.sh +83 -0
  103. data/t/t0006.ru +13 -0
  104. data/t/t0007-working_directory_no_embed_cli.sh +44 -0
  105. data/t/t0008-back_out_of_upgrade.sh +110 -0
  106. data/t/t0009-broken-app.sh +56 -0
  107. data/t/t0009-winch_ttin.sh +59 -0
  108. data/t/t0010-reap-logging.sh +55 -0
  109. data/t/t0011-active-unix-socket.sh +79 -0
  110. data/t/t0012-reload-empty-config.sh +85 -0
  111. data/t/t0013-rewindable-input-false.sh +24 -0
  112. data/t/t0013.ru +12 -0
  113. data/t/t0014-rewindable-input-true.sh +24 -0
  114. data/t/t0014.ru +12 -0
  115. data/t/t0015-configurator-internals.sh +25 -0
  116. data/t/t0016-trust-x-forwarded-false.sh +30 -0
  117. data/t/t0017-trust-x-forwarded-true.sh +30 -0
  118. data/t/t0018-write-on-close.sh +23 -0
  119. data/t/t0019-max_header_len.sh +49 -0
  120. data/t/t0020-at_exit-handler.sh +49 -0
  121. data/t/t0021-process_detach.sh +29 -0
  122. data/t/t0022-listener_names-preload_app.sh +32 -0
  123. data/t/t0100-rack-input-tests.sh +124 -0
  124. data/t/t0116-client_body_buffer_size.sh +80 -0
  125. data/t/t0116.ru +16 -0
  126. data/t/t0600-https-server-basic.sh +48 -0
  127. data/t/t9000-preread-input.sh +48 -0
  128. data/t/t9001-oob_gc.sh +47 -0
  129. data/t/t9002-oob_gc-path.sh +75 -0
  130. data/t/test-lib.sh +113 -0
  131. data/t/write-on-close.ru +11 -0
  132. data/test/aggregate.rb +15 -0
  133. data/test/benchmark/README +50 -0
  134. data/test/benchmark/dd.ru +18 -0
  135. data/test/benchmark/stack.ru +8 -0
  136. data/test/exec/README +5 -0
  137. data/test/exec/test_exec.rb +1041 -0
  138. data/test/test_helper.rb +300 -0
  139. data/test/unit/test_configurator.rb +158 -0
  140. data/test/unit/test_droplet.rb +28 -0
  141. data/test/unit/test_http_parser.rb +860 -0
  142. data/test/unit/test_http_parser_ng.rb +716 -0
  143. data/test/unit/test_http_parser_xftrust.rb +38 -0
  144. data/test/unit/test_request.rb +197 -0
  145. data/test/unit/test_response.rb +99 -0
  146. data/test/unit/test_server.rb +289 -0
  147. data/test/unit/test_signals.rb +207 -0
  148. data/test/unit/test_sni_hostnames.rb +47 -0
  149. data/test/unit/test_socket_helper.rb +192 -0
  150. data/test/unit/test_stream_input.rb +204 -0
  151. data/test/unit/test_tee_input.rb +296 -0
  152. data/test/unit/test_upload.rb +306 -0
  153. data/test/unit/test_util.rb +99 -0
  154. data/unicorn.gemspec +44 -0
  155. metadata +333 -0
data/t/oob_gc.ru ADDED
@@ -0,0 +1,21 @@
1
+ #\-E none
2
+ require 'unicorn/oob_gc'
3
+ use Rack::ContentLength
4
+ use Rack::ContentType, "text/plain"
5
+ use Unicorn::OobGC
6
+ $gc_started = false
7
+
8
+ # Mock GC.start
9
+ def GC.start
10
+ ObjectSpace.each_object(BasicSocket) do |x|
11
+ next if Unicorn::HttpServer::LISTENERS.include?(x)
12
+ x.closed? or abort "not closed #{x}"
13
+ end
14
+ $gc_started = true
15
+ end
16
+ run lambda { |env|
17
+ if "/gc_reset" == env["PATH_INFO"] && "POST" == env["REQUEST_METHOD"]
18
+ $gc_started = false
19
+ end
20
+ [ 200, {}, [ "#$gc_started\n" ] ]
21
+ }
data/t/oob_gc_path.ru ADDED
@@ -0,0 +1,21 @@
1
+ #\-E none
2
+ require 'unicorn/oob_gc'
3
+ use Rack::ContentLength
4
+ use Rack::ContentType, "text/plain"
5
+ use Unicorn::OobGC, 5, /BAD/
6
+ $gc_started = false
7
+
8
+ # Mock GC.start
9
+ def GC.start
10
+ ObjectSpace.each_object(BasicSocket) do |x|
11
+ next if Unicorn::HttpServer::LISTENERS.include?(x)
12
+ x.closed? or abort "not closed #{x}"
13
+ end
14
+ $gc_started = true
15
+ end
16
+ run lambda { |env|
17
+ if "/gc_reset" == env["PATH_INFO"] && "POST" == env["REQUEST_METHOD"]
18
+ $gc_started = false
19
+ end
20
+ [ 200, {}, [ "#$gc_started\n" ] ]
21
+ }
data/t/pid.ru ADDED
@@ -0,0 +1,3 @@
1
+ use Rack::ContentLength
2
+ use Rack::ContentType, "text/plain"
3
+ run lambda { |env| [ 200, {}, [ "#$$\n" ] ] }
@@ -0,0 +1,17 @@
1
+ #\-E none
2
+ require 'digest/sha1'
3
+ require 'unicorn/preread_input'
4
+ use Rack::ContentLength
5
+ use Rack::ContentType, "text/plain"
6
+ use Unicorn::PrereadInput
7
+ nr = 0
8
+ run lambda { |env|
9
+ $stderr.write "app dispatch: #{nr += 1}\n"
10
+ input = env["rack.input"]
11
+ dig = Digest::SHA1.new
12
+ while buf = input.read(16384)
13
+ dig.update(buf)
14
+ end
15
+
16
+ [ 200, {}, [ "#{dig.hexdigest}\n" ] ]
17
+ }
@@ -0,0 +1,21 @@
1
+ # SHA1 checksum generator
2
+ require 'digest/sha1'
3
+ use Rack::ContentLength
4
+ cap = 16384
5
+ app = lambda do |env|
6
+ /\A100-continue\z/i =~ env['HTTP_EXPECT'] and
7
+ return [ 100, {}, [] ]
8
+ digest = Digest::SHA1.new
9
+ input = env['rack.input']
10
+ input.size if env["PATH_INFO"] == "/size_first"
11
+ input.rewind if env["PATH_INFO"] == "/rewind_first"
12
+ if buf = input.read(rand(cap))
13
+ begin
14
+ raise "#{buf.size} > #{cap}" if buf.size > cap
15
+ digest.update(buf)
16
+ end while input.read(rand(cap), buf)
17
+ end
18
+
19
+ [ 200, {'Content-Type' => 'text/plain'}, [ digest.hexdigest << "\n" ] ]
20
+ end
21
+ run app
data/t/sslgen.sh ADDED
@@ -0,0 +1,71 @@
1
+ #!/bin/sh
2
+ set -e
3
+
4
+ lock=$0.lock
5
+ while ! mkdir $lock 2>/dev/null
6
+ do
7
+ echo >&2 "PID=$$ waiting for $lock"
8
+ sleep 1
9
+ done
10
+ pid=$$
11
+ trap 'if test $$ -eq $pid; then rmdir $lock; fi' EXIT
12
+
13
+ certinfo() {
14
+ echo US
15
+ echo Hell
16
+ echo A Very Special Place
17
+ echo Monkeys
18
+ echo Poo-Flingers
19
+ echo 127.0.0.1
20
+ echo kgio@bogomips.org
21
+ }
22
+
23
+ certinfo2() {
24
+ certinfo
25
+ echo
26
+ echo
27
+ }
28
+
29
+ ca_certinfo () {
30
+ echo US
31
+ echo Hell
32
+ echo An Even More Special Place
33
+ echo Deranged Monkeys
34
+ echo Poo-Hurlers
35
+ echo 127.6.6.6
36
+ echo unicorn@bogomips.org
37
+ }
38
+
39
+ openssl genrsa -out ca.key 1024
40
+ ca_certinfo | openssl req -new -x509 -days 666 -key ca.key -out ca.crt
41
+
42
+ openssl genrsa -out bad-ca.key 1024
43
+ ca_certinfo | openssl req -new -x509 -days 666 -key bad-ca.key -out bad-ca.crt
44
+
45
+ openssl genrsa -out server.key 1024
46
+ certinfo2 | openssl req -new -key server.key -out server.csr
47
+
48
+ openssl x509 -req -days 666 \
49
+ -in server.csr -CA ca.crt -CAkey ca.key -set_serial 1 -out server.crt
50
+ n=2
51
+ mk_client_cert () {
52
+ CLIENT=$1
53
+ openssl genrsa -out $CLIENT.key 1024
54
+ certinfo2 | openssl req -new -key $CLIENT.key -out $CLIENT.csr
55
+
56
+ openssl x509 -req -days 666 \
57
+ -in $CLIENT.csr -CA $CA.crt -CAkey $CA.key -set_serial $n \
58
+ -out $CLIENT.crt
59
+ rm -f $CLIENT.csr
60
+ n=$(($n + 1))
61
+ }
62
+
63
+ CA=ca
64
+ mk_client_cert client1
65
+ mk_client_cert client2
66
+
67
+ CA=bad-ca mk_client_cert bad-client
68
+
69
+ rm -f server.csr
70
+
71
+ echo OK
@@ -0,0 +1,50 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ t_plan 8 "simple HTTP connection tests"
4
+
5
+ t_begin "setup and start" && {
6
+ unicorn_setup
7
+ unicorn -D -c $unicorn_config env.ru
8
+ unicorn_wait_start
9
+ }
10
+
11
+ t_begin "single request" && {
12
+ curl -sSfv http://$listen/
13
+ }
14
+
15
+ t_begin "check stderr has no errors" && {
16
+ check_stderr
17
+ }
18
+
19
+ t_begin "HTTP/0.9 request should not return headers" && {
20
+ (
21
+ printf 'GET /\r\n'
22
+ cat $fifo > $tmp &
23
+ wait
24
+ echo ok > $ok
25
+ ) | socat - TCP:$listen > $fifo
26
+ }
27
+
28
+ t_begin "env.inspect should've put everything on one line" && {
29
+ test 1 -eq $(wc -l < $tmp)
30
+ }
31
+
32
+ t_begin "no headers in output" && {
33
+ if grep ^Connection: $tmp
34
+ then
35
+ die "Connection header found in $tmp"
36
+ elif grep ^HTTP/ $tmp
37
+ then
38
+ die "HTTP/ found in $tmp"
39
+ fi
40
+ }
41
+
42
+ t_begin "killing succeeds" && {
43
+ kill $unicorn_pid
44
+ }
45
+
46
+ t_begin "check stderr has no errors" && {
47
+ check_stderr
48
+ }
49
+
50
+ t_done
@@ -0,0 +1,53 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ t_plan 7 "reload config.ru error with preload_app true"
4
+
5
+ t_begin "setup and start" && {
6
+ unicorn_setup
7
+ rtmpfiles ru
8
+
9
+ cat > $ru <<\EOF
10
+ use Rack::ContentLength
11
+ use Rack::ContentType, "text/plain"
12
+ x = { "hello" => "world" }
13
+ run lambda { |env| [ 200, {}, [ x.inspect << "\n" ] ] }
14
+ EOF
15
+ echo 'preload_app true' >> $unicorn_config
16
+ unicorn -D -c $unicorn_config $ru
17
+ unicorn_wait_start
18
+ }
19
+
20
+ t_begin "hit with curl" && {
21
+ out=$(curl -sSf http://$listen/)
22
+ test x"$out" = x'{"hello"=>"world"}'
23
+ }
24
+
25
+ t_begin "introduce syntax error in rackup file" && {
26
+ echo '...' >> $ru
27
+ }
28
+
29
+ t_begin "reload signal succeeds" && {
30
+ kill -HUP $unicorn_pid
31
+ while ! egrep '(done|error) reloading' $r_err >/dev/null
32
+ do
33
+ sleep 1
34
+ done
35
+
36
+ grep 'error reloading' $r_err >/dev/null
37
+ > $r_err
38
+ }
39
+
40
+ t_begin "hit with curl" && {
41
+ out=$(curl -sSf http://$listen/)
42
+ test x"$out" = x'{"hello"=>"world"}'
43
+ }
44
+
45
+ t_begin "killing succeeds" && {
46
+ kill $unicorn_pid
47
+ }
48
+
49
+ t_begin "check stderr" && {
50
+ check_stderr
51
+ }
52
+
53
+ t_done
@@ -0,0 +1,49 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ t_plan 6 "config variables conflict with preload_app"
4
+
5
+ t_begin "setup and start" && {
6
+ unicorn_setup
7
+ rtmpfiles ru rutmp
8
+
9
+ cat > $ru <<\EOF
10
+ use Rack::ContentLength
11
+ use Rack::ContentType, "text/plain"
12
+ config = ru = { "hello" => "world" }
13
+ run lambda { |env| [ 200, {}, [ ru.inspect << "\n" ] ] }
14
+ EOF
15
+ echo 'preload_app true' >> $unicorn_config
16
+ unicorn -D -c $unicorn_config $ru
17
+ unicorn_wait_start
18
+ }
19
+
20
+ t_begin "hit with curl" && {
21
+ out=$(curl -sSf http://$listen/)
22
+ test x"$out" = x'{"hello"=>"world"}'
23
+ }
24
+
25
+ t_begin "modify rackup file" && {
26
+ sed -e 's/world/WORLD/' < $ru > $rutmp
27
+ mv $rutmp $ru
28
+ }
29
+
30
+ t_begin "reload signal succeeds" && {
31
+ kill -HUP $unicorn_pid
32
+ while ! egrep '(done|error) reloading' < $r_err >/dev/null
33
+ do
34
+ sleep 1
35
+ done
36
+
37
+ grep 'done reloading' $r_err >/dev/null
38
+ }
39
+
40
+ t_begin "hit with curl" && {
41
+ out=$(curl -sSf http://$listen/)
42
+ test x"$out" = x'{"hello"=>"WORLD"}'
43
+ }
44
+
45
+ t_begin "killing succeeds" && {
46
+ kill $unicorn_pid
47
+ }
48
+
49
+ t_done
@@ -0,0 +1,94 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ t_plan 11 "parser error test"
4
+
5
+ t_begin "setup and startup" && {
6
+ unicorn_setup
7
+ unicorn -D env.ru -c $unicorn_config
8
+ unicorn_wait_start
9
+ }
10
+
11
+ t_begin "send a bad request" && {
12
+ (
13
+ printf 'GET / HTTP/1/1\r\nHost: example.com\r\n\r\n'
14
+ cat $fifo > $tmp &
15
+ wait
16
+ echo ok > $ok
17
+ ) | socat - TCP:$listen > $fifo
18
+ test xok = x$(cat $ok)
19
+ }
20
+
21
+ dbgcat tmp
22
+
23
+ t_begin "response should be a 400" && {
24
+ grep -F 'HTTP/1.1 400 Bad Request' $tmp
25
+ }
26
+
27
+ t_begin "send a huge Request URI (REQUEST_PATH > (12 * 1024))" && {
28
+ rm -f $tmp
29
+ cat $fifo > $tmp &
30
+ (
31
+ set -e
32
+ trap 'echo ok > $ok' EXIT
33
+ printf 'GET /'
34
+ for i in $(awk </dev/null 'BEGIN{for(i=0;i<1024;i++) print i}')
35
+ do
36
+ printf '0123456789ab'
37
+ done
38
+ printf ' HTTP/1.1\r\nHost: example.com\r\n\r\n'
39
+ ) | socat - TCP:$listen > $fifo || :
40
+ test xok = x$(cat $ok)
41
+ wait
42
+ }
43
+
44
+ t_begin "response should be a 414 (REQUEST_PATH)" && {
45
+ grep -F 'HTTP/1.1 414 Request-URI Too Long' $tmp
46
+ }
47
+
48
+ t_begin "send a huge Request URI (QUERY_STRING > (10 * 1024))" && {
49
+ rm -f $tmp
50
+ cat $fifo > $tmp &
51
+ (
52
+ set -e
53
+ trap 'echo ok > $ok' EXIT
54
+ printf 'GET /hello-world?a'
55
+ for i in $(awk </dev/null 'BEGIN{for(i=0;i<1024;i++) print i}')
56
+ do
57
+ printf '0123456789'
58
+ done
59
+ printf ' HTTP/1.1\r\nHost: example.com\r\n\r\n'
60
+ ) | socat - TCP:$listen > $fifo || :
61
+ test xok = x$(cat $ok)
62
+ wait
63
+ }
64
+
65
+ t_begin "response should be a 414 (QUERY_STRING)" && {
66
+ grep -F 'HTTP/1.1 414 Request-URI Too Long' $tmp
67
+ }
68
+
69
+ t_begin "send a huge Request URI (FRAGMENT > 1024)" && {
70
+ rm -f $tmp
71
+ cat $fifo > $tmp &
72
+ (
73
+ set -e
74
+ trap 'echo ok > $ok' EXIT
75
+ printf 'GET /hello-world#a'
76
+ for i in $(awk </dev/null 'BEGIN{for(i=0;i<64;i++) print i}')
77
+ do
78
+ printf '0123456789abcdef'
79
+ done
80
+ printf ' HTTP/1.1\r\nHost: example.com\r\n\r\n'
81
+ ) | socat - TCP:$listen > $fifo || :
82
+ test xok = x$(cat $ok)
83
+ wait
84
+ }
85
+
86
+ t_begin "response should be a 414 (FRAGMENT)" && {
87
+ grep -F 'HTTP/1.1 414 Request-URI Too Long' $tmp
88
+ }
89
+
90
+ t_begin "server stderr should be clean" && check_stderr
91
+
92
+ t_begin "term signal sent" && kill $unicorn_pid
93
+
94
+ t_done
@@ -0,0 +1,51 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+
4
+ t_plan 4 "config.ru inside alt working_directory"
5
+
6
+ t_begin "setup and start" && {
7
+ unicorn_setup
8
+ rtmpfiles unicorn_config_tmp
9
+ rm -rf $t_pfx.app
10
+ mkdir $t_pfx.app
11
+
12
+ cat > $t_pfx.app/config.ru <<EOF
13
+ #\--daemonize --host $host --port $port
14
+ use Rack::ContentLength
15
+ use Rack::ContentType, "text/plain"
16
+ run lambda { |env| [ 200, {}, [ "#{\$master_ppid}\\n" ] ] }
17
+ EOF
18
+ # we have --host/--port in config.ru instead
19
+ grep -v ^listen $unicorn_config > $unicorn_config_tmp
20
+
21
+ # the whole point of this exercise
22
+ echo "working_directory '$t_pfx.app'" >> $unicorn_config_tmp
23
+
24
+ # allows ppid to be 1 in before_fork
25
+ echo "preload_app true" >> $unicorn_config_tmp
26
+ cat >> $unicorn_config_tmp <<\EOF
27
+ before_fork do |server,worker|
28
+ $master_ppid = Process.ppid # should be zero to detect daemonization
29
+ end
30
+ EOF
31
+
32
+ mv $unicorn_config_tmp $unicorn_config
33
+
34
+ # rely on --daemonize switch, no & or -D
35
+ unicorn -c $unicorn_config
36
+ unicorn_wait_start
37
+ }
38
+
39
+ t_begin "hit with curl" && {
40
+ body=$(curl -sSf http://$listen/)
41
+ }
42
+
43
+ t_begin "killing succeeds" && {
44
+ kill $unicorn_pid
45
+ }
46
+
47
+ t_begin "response body ppid == 1 (daemonized)" && {
48
+ test "$body" -eq 1
49
+ }
50
+
51
+ t_done